J'essaie actuellement d'apprendre à utiliser des pointeurs intelligents. Cependant, en faisant quelques expériences, j'ai découvert la situation suivante pour laquelle je ne pouvais pas trouver de solution satisfaisante:
Imaginez que vous ayez un objet de classe A étant parent d'un objet de classe B (l'enfant), mais que les deux devraient se connaître:
class A;
class B;
class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);
// How to do pass the pointer correctly?
// child->setParent(this); // wrong
// ^^^^
}
private:
std::list<std::shared_ptr<B>> children;
};
class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};
private:
std::shared_ptr<A> parent;
};
La question est de savoir comment un objet de classe A peut-il passer un std::shared_ptr
de lui-même ( this
) à son enfant?
Il existe des solutions pour les pointeurs partagés Boost ( Obtenir un boost::shared_ptr
forthis
), mais comment gérer cela en utilisant les std::
pointeurs intelligents?
c++
this
shared-ptr
this-pointer
Icare
la source
la source
Réponses:
Il y a
std::enable_shared_from_this
juste pour cela. Vous en héritez et vous pouvez appeler.shared_from_this()
depuis l'intérieur de la classe. De plus, vous créez ici des dépendances circulaires qui peuvent entraîner des fuites de ressources. Cela peut être résolu avec l'utilisation destd::weak_ptr
. Donc, votre code pourrait ressembler à ceci (en supposant que les enfants dépendent de l'existence du parent et non l'inverse):Notez cependant que l'appel
.shared_from_this()
requiert qu'ilthis
appartiennestd::shared_ptr
au point d'appel. Cela signifie que vous ne pouvez plus créer un tel objet sur la pile et que vous ne pouvez généralement pas appeler.shared_from_this()
depuis un constructeur ou un destructeur.la source
shared_ptr
basé sur une construction par défautshared_ptr
et ce que vous voulez pointer vers ...shared_ptr
ne sont pas pertinents pour cette question.shared_from_this
Les conditions préalables stipulent clairement que l 'objet doit être possédé (et non simplement indiqué) par certainsshared_ptr
au moment de l' appel.shared_ptr
est requise au moment de l'appel, mais dans un modèle d'utilisation typique, c'est-à-dire quelque chose commeshared_ptr<Foo> p(new Foo());
,shared_ptr
assume la propriété de l'objet seulement après sa construction complète. Il est possible de contourner cela en créantshared_ptr
dans le constructeur initialisé avecthis
et en le stockant quelque part non local (par exemple dans un argument de référence) pour qu'il ne meure pas lorsque le constructeur se termine. Mais ce scénario alambiqué ne sera probablement pas nécessaire.Vous avez plusieurs problèmes dans votre conception, qui semblent provenir de votre mauvaise compréhension des pointeurs intelligents.
Les pointeurs intelligents sont utilisés pour déclarer la propriété. Vous brisez cela en déclarant que les deux parents possèdent tous les enfants, mais aussi que chaque enfant possède son parent. Les deux ne peuvent pas être vrais.
En outre, vous renvoyez un pointeur faible dans
getChild()
. Ce faisant, vous déclarez que l'appelant ne devrait pas se soucier de la propriété. Maintenant, cela peut être très limitant, mais aussi ce faisant, vous devez vous assurer que l'enfant en question ne sera pas détruit tant que des pointeurs faibles sont toujours détenus, si vous utilisiez un pointeur intelligent, il serait trié par lui-même .Et la dernière chose. Habituellement, lorsque vous acceptez de nouvelles entités, vous devez généralement accepter des pointeurs bruts. Le pointeur intelligent peut avoir sa propre signification pour échanger des enfants entre parents, mais pour un usage général, vous devez accepter les pointeurs bruts.
la source