Yes, this does leak. The compiler automatically provides an extra method because you have not defined it. The code it generates is equivalent to this:
B & B::operator=(const B & other)
{
mpI = other.mpI;
return *this;
}
This means that the following stuff happens:
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!
This is obviously bad. This is likely to occur in any instance that you violate the rule of three. You have defined a non-trivial destructor and also a copy constructor. You have not defined a copy assignment, though. The rule of three is that if you define any of the above, you should always define all three.
Instead, do the following:
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
}