Question Comment initialiser un shared_ptr membre d'une classe?


Je ne suis pas sûr d'un bon moyen d'initialiser un shared_ptr qui est membre d'une classe. Pouvez-vous me dire si la façon dont je choisis C::foo() est bien, ou y a-t-il une meilleure solution?

class A
{
  public:
    A();
};

class B
{
  public:
    B(A* pa);
};

class C
{
    boost::shared_ptr<A> mA;
    boost::shared_ptr<B> mB;
    void foo();
};

void C::foo() 
{
    A* pa = new A;
    mA = boost::shared_ptr<A>(pa);
    B* pB = new B(pa);
    mB = boost::shared_ptr<B>(pb);
}

35
2017-08-23 07:20


origine


Réponses:


Votre code est tout à fait correct (ça marche), mais vous pouvez utiliser la liste d'initialisation, comme ceci:

C::C() :
  mA(new A),
  mB(new B(mA.get())
{
}

Ce qui est encore plus correct et aussi sûr.

Si, pour quelque raison que ce soit, new A ou new B jette, vous n'aurez aucune fuite.

Si new A jette, puis aucune mémoire n'est allouée, et l'exception interrompt également votre constructeur. Rien n'a été construit.

Si new B jette, et l'exception annulera toujours votre constructeur: mA sera détruit correctement.

Bien sûr, depuis une instance de B nécessite un pointeur vers une instance de A, l'ordre de déclaration des membres les questions.

L'ordre de déclaration du membre est correct dans votre exemple, mais s'il était inversé, votre compilateur se plaindrait probablement de mB être initialisé avant mA et l'instanciation de mB serait probablement échouer (depuis mA ne serait pas encore construit, appelant ainsi mA.get() invoque un comportement non défini).


Je suggère également que vous utilisez un shared_ptr<A> au lieu d'un A* comme paramètre pour votre B constructeur (si cela fait sens et si vous pouvez accepter le peu de frais généraux). Ce serait probablement plus sûr.

Peut-être est-il garanti qu'une instance de B ne peut pas vivre sans une instance de A et puis mon conseil ne s'applique pas, mais nous manquons de contexte ici pour donner un conseil définitif à ce sujet.


30
2017-08-23 07:22