Да, это действительно утечка.Компилятор автоматически предоставляет дополнительный метод, потому что вы его не определили.Генерируемый код эквивалентен следующему:
B & B::operator=(const B & other)
{
mpI = other.mpI;
return *this;
}
Это означает, что происходит следующее:
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!
Это явно плохо.Это может произойти в любом случае, если вы нарушаете правило трех .Вы определили нетривиальный деструктор, а также конструктор копирования.Вы не определили назначение копирования, однако.Правило трех состоит в том, что если вы определяете любое из вышеперечисленного, вы всегда должны определять все три.
Вместо этого выполните следующее:
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
}