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
What makes you think the object n points to should be deleted by default? The default destructor destroys the pointer, not what it's pointing to.
Edit: I'll see if I can make this a little more clear.
If you had a local pointer, and it went out of scope, would you expect the object it points to to be destroyed?
{
Thing* t = new Thing;
// do some stuff here
// no "delete t;"
}
The t pointer is cleaned up, but the Thing it points to is not. This is a leak. Essentially the same thing is happening in your class.
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.
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.
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:
class M
{
N n;
public:
M() : n()
{
}
};
It is incorrect to say that the destructor deletes members. It invokes the destructor of each member (and base class), which for built-in types (like pointers) means doing nothing.
Matching news with deletes is your responsibility (either manually, or with the help of smart pointers).
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 the N* destructor is being called which, it does NOT destruct whatever object n is pointing to. Think of the N*'s destructor as if it were an int'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.
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 and M::~M() is called, its variable n really is destroyed. The problem is that n is a N *, so while the pointer is destroyed, the thing it points to is not.
delete does not work like this. Consider your simple statement:
delete n;
The above statement destroys the thing that n points to, which is an object of type N. It does not destroy n itself, which is an N * pointer.
There is a very good reason that M::~M() does not automatically call delete n; which is this: the N object referred to might be shared between several M objects, and if one M were destroyed, the rest would lose the N 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 at std::auto_ptr.
The default destructor looks like this:
~M()
{
}
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:
struct MyClass {
public:
MyClass() { .. } // doesn't matter what this does
int x;
int* p;
std::string s;
std::vector<int> v;
};
The default destructor in reality is doing this:
MyClass::~MyClass()
{
// Call destructor on member variables in reverse order
v.~std::vector<int>(); // frees memory
s.~std::string(); // frees memory
p.~int*(); // does nothing, no custom destructor
x.~int(); // does nothing, no custom destructor
}
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!).
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
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.
M destructor should have 'delete n'.
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
Related
So I have an abstract class, called MyClassParent, which MyClass inherits from. I run the following code:
for(auto e:elements){
MyClass m = *this;
MyClass * mpointer = &m;
if(mpointer->xLargerthanY(x,y)){
rv.push_back(unique_ptr<MyClassParent>(mpointer));
if(!rv[0]->solved()) cout<<"true";//works as expected
}
}
rv[0]->solved();//gives pure virtual function called error
What's strange is that rv[0]->solved() inside the for each loop works as expected, returns true if the object has x greater than y. But if I call the function from outside the for each loop, I get a pure virtual function called error, which should never happen since I override solved() in the child class. I suspect this has something to do with the unique_ptr function, as my solved method makes no changes to the object and only return true of false.
I have tested this with many other methods, they all work inside the for each loop, but as soon as I exit it, I get the pure virtual function called error.
rv[0]->solved();//gives pure virtual function called error
Of course it does. Your program has undefined behavior, so it can do anything. It's also fairly easy to distill that snippet into what's causing the problem:
MyClass *ptr;
{
MyClass m;
ptr = &m;
}
ptr->solved();
Once we get rid of all of those red herrings, we see that all the pointers in your rv container point to objects with automatic storage durations, that have since gone out of scope. Using them to access that object is just going to behave in some undefined manner.
If you want to have rv store owning pointers to copies of this, then create those copies with dynamic storage duration
for(auto e:elements){
MyClass& m = *this; // Assuming we need the reference binding
if(m.xLargerthanY(x,y)){
rv.push_back(make_unique<MyClass>(m));
}
}
And now everything points at valid objects.
Ok, let's start with a little introduction because you seem to not have a grasp on some things needed to understand smart pointers:
Automatic storage duration: the lifetime of an object is managed by the compiler. Its lifetime is defined by the scope of the variable associated.
E.g.:
{
X x; // lifetime of x starts here
// ....
} // lifetime of x ends here
Dynamic storage duration: the lifetime of an object is managed by the programmer. It starts with a call to new and ends with a call to delete (this is simplified a bit).
E.g.:
auto foo(X* x)
{
delete x; // lifetime ends with delete
}
{
X* x = new X{}; // lifetime starts with new
foo(x);
}
In C++ you should never explicitly call new / delete and use smart pointers instead.
unique_ptr (unless specified otherwise) on destruction will automatically call delete on the pointer it helds. This is the reason it must be provided with a pointer to a dynamic object i.e. allocated with new. This is one of your problems.
X x;
std::unique_ptr<X> p{&x};
// p receives a pointer to an automatic storage duration
// this is 100% wrong. The destructor for x would be called twice
// once as part of the automatic lifetime of x
// and then as part of the destructor of p
// resulting in UB
this is what you do here:
MyClass m = ...;
MyClass * mpointer = &m;
unique_ptr<MyClassParent>(mpointer);
// unique_ptr receives a pointer to an automatic storage duration object
As if that weren't enough the other problem you have is that you access a dangling pointer.
The scope of m is within the for. The vector holds pointers to such objects and those objects go out of scope after each iteration. When you do rv[0] you access an object whose lifetime has ended. Undefined behavior again.
I hope you have a better understanding of what unique_ptr does and what problem it solves. The solution is - as Storry Teller showed - to use make_unique.
What make_unique does: it calls new and creates an unique_ptr from that pointer returned by new. You could do this by hand yourself but you shouldn't because of other problems: Differences between std::make_unique and std::unique_ptr
As pointed by #StoryTeller this is undefined behavior, but let me explain why it behaves the way it does in this case. Since it is undefined behavior, there is no guarantee it will behave this way in different compilers or systems, but I will explain why there is a good chance it will:
for(auto e:elements){
MyClass m = *this;
MyClass * mpointer = &m;
if(mpointer->xLargerthanY(x,y)){
rv.push_back(unique_ptr<MyClassParent>(mpointer));
if(!rv[0]->solved()) cout<<"true";//works as expected
}
}
rv[0]->solved();//gives pure virtual function called error
Here
for(auto e:elements){
MyClass m = *this;
....
}
A pointer to m is stored into the rv vector. But when m exists scope, the object is being destroyed. The code implicitly calls MyClass::~MyClass(), which in the end replaces the virtual table of the object. First the derived class is being destroyed, and at the last step of this destruction the virtual table is replaced so that the object no has the virtual table of the base. In the base, solved() is pure virtual, so calling:
rv[0]->solved();
so calling this function finds the definition of the base, only. The derived object no longer exists, so it can't be used. In this case, in the base class, resolved() is pure virtual, and has no body. That's why it crashes the way it does. If you had a non-virtual resolved() in the base, then there is a good chance that you'd have a different crash, since the object had been destroyed already.
Note that even if this code did not crash, then later on, when rv is destroyed things become messy. The pointers inside rv point to the stack, but std::unique_ptr calls delete and assumes that the object is on the heap. Either that will crash immediately, since this is an illegal pointer, the heap/stack will be trashed, or it will be simply ignored. The exact behavior is unknown, since this is also undefined behavior.
Here is a simpler case when you'd get a similar problem:
class Base
{
public:
virtual ~Base() { bar(); }
virtual void foo() = 0;
void bar() { foo(); }
};
class Derived: public Base
{
public:
void foo() override { };
};
int main()
{
Derived b;
}
To avoid keep having to use -> and instead work directly with the object, is it acceptable practice to do:
obj x = *(new obj(...));
...
delete &obj;
This is not just poor practice, but:
Leaking memory (most likely, unless you are using some pattern that is not visible from the code you provided), since obj will store a copy of the original object created by the new expression, and the pointer to that object returned by new is lost;
Most importantly, undefined behavior, since you are passing to delete a pointer to an object that was not allocated with new. Per paragraph 5.3.5/2 of the C++11 Standard:
[...] In the first alternative (delete object), the value of the operand of delete may be a null pointer
value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8)
representing a base class of such an object (Clause 10). If not, the behavior is undefined.
No, and in fact this leads to a leak. x is copy initialized, so the original object pointed to by new obj is lost.
Just use
obj x(...);
No need for dynamic allocation. Or
obj x = obj(...);
if you must (doubt it).
Certainly not; that copies the dynamic object to an automatic variable, loses the only pointer to it, and then attempts to delete the automatic copy. You've got a memory leak and an invalid deletion.
Much better would be to use an automatic variable in the first place:
obj x(...);
...
// no need to delete anything
or, if it really must be dynamic for some reason (because it's too big for the stack, or you don't always want to destroy it here), then use a smart pointer, and a reference if you really don't like ->
std::unique_ptr<obj> p(new obj(...));
obj & x = *p;
...
// still no need to delete anything
Changing your x into a reference would be valid (as long as you're careful that exceptions, early function returns, etc. won't cause a leak), but would cause howls of confusion among anyone unfortunate enough to have to maintain it.
You cannot delete your object properly if you do it like that.
Implicitly you do the following.
class A
{
public:
int test (void) { return 1; }
};
int main (void)
{
A * p = new A;
A v(*p);
//...
delete &v; // &v != p and v is not constructed via new!
return 0;
}
If you want to work with an object-like-syntax you can bind a reference to the object.
class A
{
public:
int test (void) { return 1; }
};
int main (void)
{
A * p = new A;
A & r = *p;
int i = r.test();
delete p;
return 0;
}
If you delete your object through the same pointer, there will be no leak.
To avoid keep having to use -> and instead work directly with the object, is it acceptable practice to do:
obj x = *(new obj(...));
...
delete &obj;
This is not just poor practice, but:
Leaking memory (most likely, unless you are using some pattern that is not visible from the code you provided), since obj will store a copy of the original object created by the new expression, and the pointer to that object returned by new is lost;
Most importantly, undefined behavior, since you are passing to delete a pointer to an object that was not allocated with new. Per paragraph 5.3.5/2 of the C++11 Standard:
[...] In the first alternative (delete object), the value of the operand of delete may be a null pointer
value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8)
representing a base class of such an object (Clause 10). If not, the behavior is undefined.
No, and in fact this leads to a leak. x is copy initialized, so the original object pointed to by new obj is lost.
Just use
obj x(...);
No need for dynamic allocation. Or
obj x = obj(...);
if you must (doubt it).
Certainly not; that copies the dynamic object to an automatic variable, loses the only pointer to it, and then attempts to delete the automatic copy. You've got a memory leak and an invalid deletion.
Much better would be to use an automatic variable in the first place:
obj x(...);
...
// no need to delete anything
or, if it really must be dynamic for some reason (because it's too big for the stack, or you don't always want to destroy it here), then use a smart pointer, and a reference if you really don't like ->
std::unique_ptr<obj> p(new obj(...));
obj & x = *p;
...
// still no need to delete anything
Changing your x into a reference would be valid (as long as you're careful that exceptions, early function returns, etc. won't cause a leak), but would cause howls of confusion among anyone unfortunate enough to have to maintain it.
You cannot delete your object properly if you do it like that.
Implicitly you do the following.
class A
{
public:
int test (void) { return 1; }
};
int main (void)
{
A * p = new A;
A v(*p);
//...
delete &v; // &v != p and v is not constructed via new!
return 0;
}
If you want to work with an object-like-syntax you can bind a reference to the object.
class A
{
public:
int test (void) { return 1; }
};
int main (void)
{
A * p = new A;
A & r = *p;
int i = r.test();
delete p;
return 0;
}
If you delete your object through the same pointer, there will be no leak.
I have been researching, and nothing relevant has come up, so I came here.
I am trying to avoid memory leaks, so I am wondering:
Say I have class MyClass with member ints a and b, and an int array c, which are filled in a member function:
class MyClass
{
public:
int a, b;
int c[2];
void setVariables()
{
a, b = 0;
for (int i = 0; i < 2; i++)
{
c[i] = 3;
}
}
};
int main(int argc, char* argv[])
{
MyClass* mc = new MyClass();
mc->setVariables();
delete mc;
}
Now, after I call delete mc, will a, b, and all the contents of c be deleted as well? Or will I have to do that explicitly in the destructor of MyClass?
The rule is very simple: every object created with new must be destroyed exactly once with delete; every array created with new[] must be destroyed exactly once with delete[]; everything else must not be deleted. So your code is correct; you are deleting mc after creating it with new, and not deleting the members which were not created with new.
Applying the rule can be quite tricky when the program flow gets complicated (especially when exceptions are involved); for that reason, it is much better not to delete objects yourself, but to immediately use the result of new to initialise a smart pointer to manage the object for you.
When delete mc is executed, the compiler calls the destructor of the object (MyClass::~MyClass()) and then deallocates the memory associated with it.
The default destructor (when you don't declare your own) calls the destructors of all member variables, in order from last to first by declaration (that is, in this case, c, then b, then a). Since those members in this example are POD types (they do not have a destructor), no work is done.
Class members are a part of the class' memory structure.
So when you free that memory, the members are freed with it.
NOTE:
If you have pointers they are destroyed too, BUT the memory they point at isn't destroyed.
More about class memory consumption:
C++ Classes
Variables inside of a class have class scope and are destroyed when the class is. The only thing you need to worry about is pointers -- those will need to be addressed appropriately in your destructor.
For your specific example, the answer is yes. That's because you allocated the member variables on the stack. If you had used new to allocate memory for the member variables the answer would be no and would require you to explicitly delete the member variables in the class' destructor.
class MyClass(): heapVariabl(NULL)
{
MyClass()
{}
~MyClass()
{
delete heapVariable;
}
int a, b;
int[2] c;
int *heapVariable;
void setVariables()
{
a, b = 0;
heapVariable = new int; // <- requires deletion in destructor to free memory
*heapVariable = 0;
for (int i = 0; i < 2; i++)
{
c[i] = 3;
}
}
}
When you free an object, all of its member variables are automatically freed as well. So, in your case, yes, a, b and c are all freed.
However, if one of your member variables is a pointer, only the pointer itself is automatically freed, not the object it points to - this is the most common case for having to write your own destructor.
delete will reclaim the memory that your object contains. If your type maintains pointers to dynamically allocated memory then you will need to clean those up inside of your destructor.
As for your specific quesiton:
after I call delete mc, will a, b, and all the contents of c be deleted as well? Or will I have to do that explicitly in the destructor of MyClass?
They will be cleaned up for you as they were not allocated dynamically.
Your three variables were not allocated with new so there would be no need to delete them at all.
They would be destructed when your class is deleted (as they were allocated when your class was newd), but that's not the same as being deleted.
in the following code:
class x
{
private:
someRef& m_ref;
public:
x(someRef& someRef):m_ref(someRef)
{
}
do I need to do:
~x()
{
delete m_ref;
}
which by the way doesnt work without getting the pointer...
basically I'm asking: Do I need to call a destructor on a reference member?
No.
You only need to delete an object if you own it. If you were passed a reference, it means that someone else owns it, thus it's unnecessary and thankfully the language prevents it.
I don't think one actually strictly speaking ever deletes even pointers. What you delete are dynamically allocated objects (or arrays of objects) that the pointer is a handle for. If the object originates from a call to new and it is the responsibility of this class to clean up after this object, then you call delete.
It is technically possible that a reference might be referring to a dynamically allocated object:
int main()
{
//in principle a reference can also refer to a dynamically allocated object
x var(*new someRef);
}
//and if that is the intended usage:
x::~x()
{
delete &m_ref;
}
However, this would be incredibly bad style. By convention, the "owning" handle of a dynamically allocated object should not be a reference.
No. You can only delete pointers, not references, and even then you must only delete objects that you allocated using the new operator. And then you must be sure to delete them only once. Here is the case in which you would need to use delete in your destructor:
class x
{
private:
someObj* m_ptr;
public:
x():m_ptr(new someObj())
{
}
~x()
{
delete m_ptr;
}
But in general it's best to avoid even this and use smart pointers instead.
I want to clarify some misconceptions you seem to have that are beyond the intent of your question:
When a class's destructor is called all of it's members' destructors get called as well.
Calling delete is not the same as calling the destructor. delete explicitly calls the destructor and also calls operator delete at the objects location, it is a 2 part thing.
For a small bit of extra clarification I want to offer the following:
int *pi = new int;
//int& ir = pi; // can't do
// this a reference to the pointer but it is an error
// because or the type difference int& vs int* and
// static_cast won't help. reinterpret_cast would allow
// the assignment to take place but not help the 'delete ir'
int& ir = *pi; // this is OK - a reference to what the pointer points to.
// In other words, the the address of the int on the heap.
//delete ir; // can't do, it is a reference and you can't delete non-pointers.
delete &ir; // this works but it is still not "deleting a reference".
// The reference 'ir' is another name for the heap-based int.
// So, &ir is the address of that int, essentially a pointer.
// It is a pointer that is being used by delete, not a reference.