Oui, cela entraîne une fuite. Le compilateur fournit automatiquement une méthode supplémentaire car vous ne l'avez pas définie. Le code qu'il génère est équivalent à ceci:
B & B::operator=(const B & other)
{
mpI = other.mpI;
return *this;
}
Cela signifie que les choses suivantes se produit:
B b; // b.mpI = heap_object_1
B temp1; // temporary object, temp1.mpI = heap_object_2
b = temp1; // b.mpI = temp1.mpI = heap_object_2; heap_object_1 is leaked;
~temp1(); // delete heap_object_2; b.mpI = temp1.mpI = invalid heap pointer!
B temp2; // temporary object, temp1.mpI = heap_object_3
b = temp1; // b.mpI = temp2.mpI = heap_object_3;
~temp1(); // delete heap_object_3; b.mpI = temp2.mpI = invalid heap pointer!
~b(); // delete b.mpI; but b.mpI is invalid, UNDEFINED BEHAVIOR!
Ceci est évidemment mauvais. Cela est susceptible de se produire dans toute instance que vous violez le rule of three. Vous avez défini un destructeur non trivial ainsi qu'un constructeur de copie. Cependant, vous n'avez pas défini d'affectation de copie. La règle de trois est que si vous définissez l'un des éléments ci-dessus, vous devez toujours définir tous les trois.
Au lieu de cela, procédez comme suit:
class B
{
int* mpI;
public:
B() { mpI = new int; }
B(const B & other){ mpI = new int; *mpi = *(other.mpI); }
~B() { delete mpI; }
B & operator=(const B & other) { *mpI = *(other.mpI); return *this; }
};
void foobar()
{
B b;
b = B(); // causes construction
b = B(); // causes construction
}
vous devez écrire un opérateur de copie profond approprié, ou empêcher l'opérateur d'être appelé. (bonne pratique sauf si vous en avez explicitement besoin) – seand
Ok, merci. Je suppose que c'est la raison pour laquelle ils disent de définir un opérateur d'affectation privée, sauf si vous avez besoin d'affectation ... ou si je veux que cela fonctionne de manière utile, je dois définir un opérateur d'affectation. –