The C++ specification says the default destructor deletes all non-static members. Nevertheless, I can't manage to achieve that.
I have this:
class N {
public:
~N() {
std::cout << "Destroying object of type N";
}
};
class M {
public:
M() {
n = new N;
}
// ~M() { //this should happen by default
// delete n;
// }
private:
N* n;
};
Then this should print the given message, but it doesn't:
M* m = new M();
delete m; //this should invoke the default destructor
The default destructor looks like this:
The default destructor does not insert code to do anything with pointed-to things. What if you had n pointing to a stack variable? Automatically inserting a delete n would crash.
The default destructor calls the destructor on each member of the class (member.~T()). For a pointer, that's a no-op (does nothing), just like myint.~int() does nothing, but for member classes with defined destructors, the destructor is called.
Here's another example:
The default destructor in reality is doing this:
Of course, if you define a destructor, the code in your destructor runs before the member variables are destroyed (obviously, otherwise they would not be valid!).
I think you could benefit from a very simple example:
This will not print anything either.
Why ? Because the
pointer
(n
) is destructed, not the object pointed to*n
.Of course, you would not want it to destroy the object pointed to:
You should remember that unlike languages like
C#
orJava
, there are 2 ways to create objects in C++: directlyN myObject
(on the stack) or vianew
like innew N()
in which case the object is placed on the heap and YOU are reponsible for releasing it at a later time.So your destructor destroys the pointer, but not the object pointed to. Allocate the object without new (and without using a pointer) or use a
Smart Pointer
if you want it to be automatic.I think you may be confused about levels of indirection here. When an instance is destroyed, each data member does indeed get destroyed along with it. In your case, when an
M
is destroyed andM::~M()
is called, its variablen
really is destroyed. The problem is thatn
is aN *
, so while the pointer is destroyed, the thing it points to is not.delete
does not work like this. Consider your simple statement:The above statement destroys the thing that
n
points to, which is an object of typeN
. It does not destroyn
itself, which is anN *
pointer.There is a very good reason that
M::~M()
does not automatically calldelete n;
which is this: theN
object referred to might be shared between severalM
objects, and if oneM
were destroyed, the rest would lose theN
they were pointing at, leaving horrible dangling pointers everywhere. C++ does not attempt to interpret what you meant to do with your pointers, it just does what you told it to do.In short,
M
really is destroying all of its members when it is destroyed, it's just that this destruction doesn't do what you think it should do. If you want a pointer type which takes ownership of an object and destroys it when the pointer is destroyed, look atstd::auto_ptr
.Your argument might seem sound but that's not how things work for pointers.
n
is actually being destructed but, what this means is that theN*
destructor is being called which, it does NOT destruct whatever objectn
is pointing to. Think of theN*
's destructor as if it were anint
's destructor. It deletes its value, the same happens for a pointer, it deletes the address it is pointing to, but it doesn't need to delete whatever object is located at the address you just deleted.and now the expectation is :
It will only happen, if the class M is derived from N:
Only in this situation,
will call constructor of N and then constructor of M, where as
will automatically call destructor of M first and then N
Is there any reason why you use a pointer when the pointed-to object seems to belong the contained object? Just store the object by value: