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 dans C::foo()
est bonne, ou existe-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);
}
Votre code est tout à fait correct (cela fonctionne), 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 une raison quelconque, new A
Ou new B
Lance, vous n'aurez aucune fuite.
Si new A
Est lancé, aucune mémoire n'est allouée et l'exception annule également votre constructeur. Rien n'a été construit.
Si new B
Se lève et que l'exception abandonne toujours votre constructeur: mA
sera détruit correctement.
Bien sûr, comme une instance de B
nécessite un pointeur vers une instance de A
, l'ordre de déclaration des membres importe.
L'ordre de déclaration des membres est correct dans votre exemple, mais s'il était inversé, votre compilateur se plaindrait probablement de mB
d'être initialisé avant mA
et l'instanciation de mB
serait probablement échouer (puisque mA
ne serait pas encore construit, donc appeler mA.get()
invoque un comportement non défini).
Je suggérerais également que vous utilisiez un shared_ptr<A>
Au lieu d'un A*
Comme paramètre pour votre constructeur B
(if cela a du sens et si vous peut accepter les petits 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 alors mon conseil ne s'applique pas, mais nous manquons de contexte ici pour donner un conseil définitif à ce sujet .