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
Imagine something like this:
class M {
public:
M() { }
// ~M() { // If this happens by default
// delete n; // then this will delete an arbitrary pointer!
// }
private:
N* n;
};
You're on your own with pointers in C++. No one will automatically delete them for you.
The default destructor will indeed destroy all member objects. But the member object in this case is a pointer itself, not the thing it points to. This might have confused you.
However, if instead of a simple built-in pointer, you will use a smart pointer, the destruction of such a "pointer" (which is actually a class) might trigger the destruction of the object pointed to.
Try avoiding using pointers. They are last resort elements.
class N {
public:
~N() {
std::cout << "Destroying object of type N";
}
};
class M {
public:
M() {
// n = new N; no need, default constructor by default
}
// ~M() { //this should happen by default
// delete n;
// }
private:
N n; // No pointer here
};
Then use it this way
main(int, char**)
{
M m;
}
This will display Destroying object of type N
The default destructor is destroying the pointer. If you want to delete the N
with M
's default destructor, use a smart pointer. Change N * n;
to auto_ptr<N> n;
and n
will be destroyed.
Edit: As pointed out in comments, auto_ptr<>
is not the best smart pointer for all uses, but it looks like what's called for here. It specifically represents ownership: the N in an M is there for the duration of the M and no longer. Copying or assigning an auto_ptr<>
represents a change in ownership, which is usually not what you want. If you wanted to pass a pointer from M, you should pass a N *
gotten from n.get()
.
A more general solution would be boost::shared_ptr<>
, which will be in the C++0x standard. That can be used pretty much wherever a raw pointer would be used. It's not the most efficient construct, and has problems with circular references, but it's generally a safe construct.
Another edit: To answer the question in another comment, the standard behavior of the default destructor is to destroy all data members and base classes. However, deleting a raw pointer simply removes the pointer, not what it points to. After all, the implementation can't know if that's the only pointer, or the important one, or anything like that. The idea behind smart pointers is that deleting a smart pointer will at least lead to the deletion of what it points to, which is usually the desired behavior.
I think you could benefit from a very simple example:
int main(int argc, char* argv[])
{
N* n = new N();
} // n is destructed here
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:
int main(int argc, char* argv[])
{
N myObject;
{
N* n = &myObject;
} // n is destructed here, myObject is not
myObject.foo();
} // myObject is destructed here
You should remember that unlike languages like C#
or Java
, there are 2 ways to create objects in C++: directly N myObject
(on the stack) or via new
like in new 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.
Since you are using new
to create instance, it won't delete by default.
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;
};
and now the expectation is :
M* m = new M();
delete m; //this should invoke the default destructor
It will only happen, if the class M is derived from N:
class M: Class N {
...
Only in this situation,
M* m = new M()
will call constructor of N and then constructor of M, where as
delete m;
will automatically call destructor of M first and then N