Im new to this and just wanted to ask a quick question about deleting objects.
I have an object called MyClass1 and from it I have a number of other classes, MyClassA, MyClassB etc.
Now should I do this in MyClass1:
MyClass1::~MyClass1()
{
delete MyClassA;
delete MyClassB;
}
Or will everything created in MyClass1 automatically be deleted when I delete MyClass1?
Also, if I have more objects created in MyClassA and MyClassB, will these also have to be deleted manually in their respective class?
Thanks
If you're asking this, you're just learning C++, so the best advice is - neither. You should know about this stuff (dynamic allocation & memory management - see Guillaume's answer for this), but what you really should do is use RAII (google this). The proper C++ way of doing it would be:
struct MyClass1
{
MyClassA mA;
std::shared_ptr<MyClassB> mB;
MyClass1() : mB(new MyClassB)
{
}
};
See? No more destructor, which means you also don't need a copy constructor or copy assignment operator (which is where Guillaume's answer is flawed - it's missing the last two).
call delete operator only if you have created your objects with new operator
struct MyClass1
{
MyClassA mA;
MyClassB * mB;
MyClass1()
{
mB = new MyClassB;
}
~MyClass1()
{
delete mB;
}
};
You can't delete objects that aren't pointers because that's not the purpose of delete. It's meant to free dynamic memory associated with an object. That is, whatever is created with new must be deleted. You can have pointers to a class, and they can be deleted. But since nothing was allocated with new, there's no need to use delete. The class will in fact be destructed from memory at the end of the scope in which it is created. Those objects are allocated on the stack while dynamic memory is on the heap. Objects on the stack have automatic storage duration (deleted at the end of its scope, unless its declared static in which case it has "static" storage duration); moreover, objects on the heap have dynamic storage duration. Dynamic memory in C++ is controlled by you, that's why we are given new and delete (because C++ expects us to handle the memory ourselves). And otherwise deleting an object not constructed with new is undefined behavior and may lead to a crash.
If Qt, use QPointer! It is a smart pointer: nothing needed in destructor.
#include <QPointer>
class MyClass1
{
QPointer<MyClassA> pA;
QPointer<MyClassB> pB;
};
delete is applied to objects, not to classes. As a rule, calling delete (or arranging to have it called automatically, via a shared pointer, or with the RAII idiom in general) is necessary only if you called new to create the object. The exception is the return value of some (library?) call being an object that the (library's?) documentation states explicitly that the caller has to dispose of with delete (in which case, think of the call as a wrapper around a new that you have become responsible for.) Of course, APIs like that should be avoided if at all possible.
Related
I use extra brackets in my code. I thought when the destructor should be called after the local variable scope is ended but it doesn't work like this:
class TestClass {
public:
TestClass() {
printf( "TestClass()\n" );
}
~TestClass() {
printf( "~TestClass()\n" );
}
};
int main() {
int a, b, c;
{
TestClass *test = new TestClass();
}
}
It outputs:
TestClass()
So it doesn't call the destructor of the TestClass but why? If I call it manually (delete test) it calls the destructor, right. But why it doesn't call the destructor in the first case?
TestClass *test = new TestClass();
You using new which creates a dynamically allocated object (most likely placed on the heap). This type of resource needs to be manually managed by you. By managing, you should use delete on it after you have done using it.
{
TestClass *test = new TestClass();
// do something
delete test;
}
But for the most of your purposes and intents, you just have to use automatic-storage objects, which frees you the hassle of having to manually manage the object. It would also most likely to have better performance especially in short-lived objects. You should always prefer to use them unless you have a really good reason not to do so.
{
TestClass test;
// do something
}
However, if you need the semantics of dynamically allocated objects or that of pointers, it will always be better to use some mechanism to encapsulate the deletion/freeing of the object/resource for you, which also provides you additional safety especially when you are using exceptions and conditional branches. In your case, it would be better if you use std::unique_ptr.
{
std::unique_ptr<TestClass> test(new TestClass());
// auto test = std::make_unique<TestClass>(); in C++14
// do something (maybe you want to pass ownership of the pointer)
}
The following is a relevant link to help you decide whether to use automatic storage objects or dynamically allocated objects: Why should C++ programmers minimize use of 'new'?
Because you have a pointer to a dynamically allocated object. Only the pointer goes out of scope, not the object it points to. You have to call delete on the pointer in order for the pointee's destructor to get called.
Try with an automatic storage object instead:
{
TestClass test;
}
Here, the destructor will be called on exiting the scope.
The use of raw pointers to dynamically allocated objects in C++ is discouraged because it can easily lead to resource leaks like the one shown in your code example. If pointers to dynamically allocated objects are really needed, it is wise to handle them with a smart pointer, rather than to attempt to manually deal with their destruction.
This answer is good enough but just to add some more.
I see you have been coded with Java. In C++ to create variable/object in stack keyword new is not needed. Actually when you use keyword new your object is creating in heap and it doesn't destroys after leaving scope. To destroy it you need to call delete in your case delete test;
In such a structure as yours, after leaving scope you just lose pointer what points into object, so after leaving scope you cannot free memory and call destructor, but eventually OS call destructor just after exit() instruction is executed.
To sum up C++ != Java
I have the following code and I get stack overflow error can anyone please explain me What's wrong here. from my understanding this pointer points to current object so why I cant delete it in a destructor;
class Object
{
private:
static int objCount;
public:
int getCount()
{
int i =10;
return i++;
}
Object()
{
cout<< "Obj Created = "<<++objCount<<endl;
cout <<endl<<this->getCount()<<endl;
}
~Object()
{
cout<<"Destructor Called\n"<<"Deleted Obj="<<objCount--<<endl;
delete this;
}
};
int Object::objCount = 0;
int _tmain(int argc, _TCHAR* argv[])
{
{
Object obj1;
}
{
Object *obj2 = new Object();
}
getchar();
return 0;
}
You're doing delete this; in your class's destructor.
Well, delete calls the class's destructor.
You're doing delete this; in your class's destructor.
...
<!<!<!Stack Overflow!>!>!>
(Sorry guys I feel obliged to include this... this might probably spoil it sorrrryyyy!
Moral of the boring story, don't do delete this; on your destructor (or don't do it at all!)
Do [1]
Object *obj = new Object();
delete obj;
or much better, just
Object obj;
[1]#kfsone's answer more accurately points out that the stack overflow was actually triggered by obj1's destructor.
'delete this' never makes sense. Either you're causing an infinite recursion, as here, or you're deleting an object while it is still in use by somebody else. Just remove it. The object is already being deleted: that's why you're in the destructor.
The crash you are having is because of the following statement:
{
Object obj1;
}
This allocates an instance of "Object" on the stack. The scope you created it in ends, so the object goes out of scope, so the destructor (Object::~Object) is invoked.
{
Object obj1;
// automatic
obj1.~Object();
}
This means that the next instruction the application will encounter is
delete this;
There are two problems right here:
delete calls the object's destructor, so your destructor indirectly calls your destructor which indirectly calls your destructor which ...
After the destructor call, delete attempts to return the object's memory to the place where new obtains it from.
By contrast
{
Object *obj2 = new Object();
}
This creates a stack variable, obj2 which is a pointer. It allocates memory on the heap to store an instance of Object, calls it's default constructor, and stores the address of the new instance in obj2.
Then obj2 goes out of scope and nothing happens. The Object is not released, nor is it's destructor called: C++ does not have automatic garbage collection and does not do anything special when a pointer goes out of scope - it certainly doesn't release the memory.
This is a memory leak.
Rule of thumb: delete calls should be matched with new calls, delete [] with new []. In particular, try to keep new and delete in matching zones of authority. The following is an example of mismatched ownership/authority/responsibility:
auto* x = xFactory();
delete x;
Likewise
auto* y = new Object;
y->makeItStop();
Instead you should prefer
// If you require a function call to allocate it, match a function to release it.
auto* x = xFactory();
xTerminate(x); // ok, I just chose the name for humor value, Dr Who fan.
// If you have to allocate it yourself, you should be responsible for releasing it.
auto* y = new Object;
delete y;
C++ has container classes that will manage object lifetime of pointers for you, see std::shared_ptr, std::unique_ptr.
There are two issues here:
You are using delete, which is generally a code smell
You are using delete this, which has several issues
Guideline: You should not use new and delete.
Rationale:
using delete explicitly instead of relying on smart pointers (and automatic cleanup in general) is brittle, not only is the ownership of a raw pointer unclear (are you sure you should be deleting it ?) but it is also unclear whether you actually call delete on every single codepath that needs it, especially in the presence of exceptions => do your sanity (and that of your fellows) a favor, don't use it.
using new is also error-prone. First of all, are you sure you need to allocate memory on the heap ? C++ allows to allocate on the stack and the C++ Standard Library has containers (vector, map, ...) so the actual instances where dynamic allocation is necessary are few and far between. Furthermore, as mentioned, if you ever reach for dynamic allocation you should be using smart pointers; in order to avoid subtle order of execution issues it is recommend you use factory functions: make_shared and make_unique (1) to build said smart pointers.
(1) make_unique is not available in C++11, only in C++14, it can trivially be implemented though (using new, of course :p)
Guideline: You shall not use delete this.
Rationale:
Using delete this means, quite literally, sawing off the branch you are sitting on.
The argument to delete should always be a dynamically allocated pointer; therefore should you inadvertently allocate an instance of the object on the stack you are most likely to crash the program.
The execution of the method continues past this statement, for example destructors of local objects will be executed. This is like walking on the ghost of the object, don't look down!
Should a method containing this statement throw an exception or report an error, it is difficult to appraise whether the object was successfully destroyed or not; and trying again is not an option.
I have seen several example of usage, but none that could not have used a traditional alternative instead.
I use extra brackets in my code. I thought when the destructor should be called after the local variable scope is ended but it doesn't work like this:
class TestClass {
public:
TestClass() {
printf( "TestClass()\n" );
}
~TestClass() {
printf( "~TestClass()\n" );
}
};
int main() {
int a, b, c;
{
TestClass *test = new TestClass();
}
}
It outputs:
TestClass()
So it doesn't call the destructor of the TestClass but why? If I call it manually (delete test) it calls the destructor, right. But why it doesn't call the destructor in the first case?
TestClass *test = new TestClass();
You using new which creates a dynamically allocated object (most likely placed on the heap). This type of resource needs to be manually managed by you. By managing, you should use delete on it after you have done using it.
{
TestClass *test = new TestClass();
// do something
delete test;
}
But for the most of your purposes and intents, you just have to use automatic-storage objects, which frees you the hassle of having to manually manage the object. It would also most likely to have better performance especially in short-lived objects. You should always prefer to use them unless you have a really good reason not to do so.
{
TestClass test;
// do something
}
However, if you need the semantics of dynamically allocated objects or that of pointers, it will always be better to use some mechanism to encapsulate the deletion/freeing of the object/resource for you, which also provides you additional safety especially when you are using exceptions and conditional branches. In your case, it would be better if you use std::unique_ptr.
{
std::unique_ptr<TestClass> test(new TestClass());
// auto test = std::make_unique<TestClass>(); in C++14
// do something (maybe you want to pass ownership of the pointer)
}
The following is a relevant link to help you decide whether to use automatic storage objects or dynamically allocated objects: Why should C++ programmers minimize use of 'new'?
Because you have a pointer to a dynamically allocated object. Only the pointer goes out of scope, not the object it points to. You have to call delete on the pointer in order for the pointee's destructor to get called.
Try with an automatic storage object instead:
{
TestClass test;
}
Here, the destructor will be called on exiting the scope.
The use of raw pointers to dynamically allocated objects in C++ is discouraged because it can easily lead to resource leaks like the one shown in your code example. If pointers to dynamically allocated objects are really needed, it is wise to handle them with a smart pointer, rather than to attempt to manually deal with their destruction.
This answer is good enough but just to add some more.
I see you have been coded with Java. In C++ to create variable/object in stack keyword new is not needed. Actually when you use keyword new your object is creating in heap and it doesn't destroys after leaving scope. To destroy it you need to call delete in your case delete test;
In such a structure as yours, after leaving scope you just lose pointer what points into object, so after leaving scope you cannot free memory and call destructor, but eventually OS call destructor just after exit() instruction is executed.
To sum up C++ != Java
I can't help reading the bulk of forum posts on destructors and getting totally confused.
Some say to call the destructor (with delete) once for each call to new. Some say the destructor automatically gets called in a variety of circumstances i.e. when the pointer is reassigned, when the object goes out of scope. Some suggest the pointer going out of scope while being a return value where the object exists as a copy of its former self, (does this then need explicit destruction as it was originally created with a new?
There seems to be some suggestion that calling the same destructor more than once will corrupt memory so all delete calls should be partnered with *pointer = NULL; to avoid corruption. If not then some more advanced object management system would require implementing, or an iron-fisted rigour of ownership.
I can't seem to make any sense of discussions on calling sequence of destructors, i.e. does the call 1) originate at the base superclass and cascade down to the specific class, calling all virtualised destructors on the way, 2) originate at the instantiated class and move up to the superclass, or 3) originate at the particular cast the class has when it goes out of scope, then traverse both toward the instantiated and base class. Do cascading destructors
Ultimately I simply don't know strictly how or when to delete objects if ever, whether objects are responsible for deleting all objects they reference, how to cleanly handle a proper object-oriented deletion routine where an object is referenced multiple times, it's just a mess in my head. As you can see I can't really formulate a single solid question to ask, am really hoping someone can offer a clean and concise discussion of if not the single 'correct' approach, at least the industry best practice to object deletion.
There are 3 types of allocation for which destructors are called in different ways:
Automatic allocation
These objects reside in automatic memory (trivially, the stack):
int main()
{
A a;
//...
}
The destructor of a is automatically called when a goes out of scope (closing }).
Dynamic allocation
Objects reside in dynamic memory (the heap). They are allocated with new and in order for the dstructor to be called, you need to call delete:
int main()
{
A* a = new A;
delete a; //destructor called
}
In this case it was probably suggested you should assign NULL to a after the delete. There are two schools of thought regarding this (I personally wouldn't suggest it). The motivation would be that you could possibly call delete again on a and crash the program if you don't set it to NULL. Which is correct. But if you do call delete again, that's already a bug or something wrong in the logic, which shouldn't be masked by making the code appear to run correctly.
Static allocation
Objects reside in static memory. Regardless of where they are allocated, the destructor is automatically called when the program ends:
A a; //namespace scope
int main()
{
}
Here, As destructor is called when the program terminates, after main finishes.
The C++ language leaves memory management in the hand of the programmer, that is the reason for which you can find that level of confusion.
Repeating what Luchian Grigore said there are three main types of memory
automatic storage (stack)
dynamic storage (heap)
static storage
If you allocate an object in automatic storage the the object will be destroyed once the scope is terminated; for example
void foo() {
MyClass myclass_instance;
myclass_instance.doSomething();
}
in the above case when the function terminates myclass_instance is destroyed automatically.
If you instead allocate an object in the heap with new then it's your responsibility to call the destructor with delete.
In C++ also an object can have sub-objects. For example:
class MyBiggerClass {
MyClass x1;
MyClass x2;
...
};
those sub-objects are allocated in the same memory the containing object is allocated to
void foo() {
MyBiggerClass big_instance;
MyBiggerClass *p = new MyBiggerClass();
...
delete p;
}
in the above case the two sub-objects big_instance.x1 and big_instance.x2 will be allocated in automatic storage (stack), while p->x1 and p->x2 are allocated on the heap.
Note however that you don't need in this case to call delete p->x1; (compile error, p->x1 is not a pointer) or delete &(p->x1); (syntactically valid, but logical mistake because that it wasn't allocated explicitly on the heap, but as a sub-object of another object). Deleting the main object p is all that is needed.
Another complication is that an object may keep pointers to other objects instead of including them directly:
class MyOtherBigClass {
MyClass *px1;
MyClass *px2;
};
in this case it will be the constructor of MyOtherBigClass that will have to find the memory for the sub-objects and it will be ~MyOtherBigClass that will have to take care of destroying the sub-objects and freeing the memory.
In C++ destroying a raw pointer doesn't automatically destroy the content.
Base classes in simple cases can be seen just as hidden embedded sub-objects. I.e. it's like if an instance of the base object is embedded in the derived object.
class MyBaseClass {
...
};
class MyDerivedClass : MyBaseClass {
MyBaseClass __base__; // <== just for explanation of how it works: the base
// sub-object is already present, you don't
// need to declare it and it's a sub-object that
// has no name. In the C++ standard you can find
// this hidden sub-object referenced quite often.
...
};
This means that the destructor of the derived object doesn't need to call the destructor of the base object because this is taken care by the language automatically.
The case of virtual bases is more complex, but still the invocation of base destructors is automatic.
Given that memory management is in the control of the programmer there are a few strategies that have emerged to help programmers avoiding making a mess of intricate code that always ends up in object leaks or multiple destruction.
Plan carefully how you are going to handle lifetime of the instances. You cannot just leave this as an afterthought because it will be impossible to fix later. For every object instance it should be clear who creates and who destroys it.
When it's impossible to plan ahead of time when an object should be destroyed then use reference counters: for every object keep track how many pointers are referencing it and destroy the object once this number reaches zero. There are smart pointers that can take care of this for you.
Never keep around a pointer to an object that has already been destroyed.
Use containers that are classes designed explicitly to handle the lifetime of contained objects. Examples are std::vector or std::map.
If your code calls new, then it should call delete as well, yes. Except if you are using smart pointers (which will call delete for you when the pointer gets destroyed). Whenever possible, you should use smart pointers and use vector or string to avoid having to manually allocate memory using new - if you don't call new, you don't need to worry about making sure delete is called -> no memory leaks, and no problems with objects being destroyed at the wrong time, etc.
Calling delete multiple times for the same instance is definitely a bad idea.
If we have this:
class A
{
int *p;
public:
A() { p = new int[10]; }
~A() { delete [] p; }
};
class B
{
A a;
~B() { ... }
...
};
class C : public B
{
...
~C() { ... }
}
...
C *cp = new C;
....
delete cp;
then the destructor of C gets called by delete. The destructor of B is called by the C destructor, and the destructor of A gets called by the B destructor. This is automatic, and the compiler will "make sure this happens".
And if we don't call new:
...
{
C c;
...
} // Destructor for C gets called here (and B and A as describe above)
This is merely for curiosity sake because I have not used new and delete in c++ except for the most basic uses.
I know that delete releases memory. The thing I'm wondering is how does it handle more complex cases?
For instance, if I have a user-defined class like this:
class MyClass
{
public:
MyClass();
~MyClass()
{
delete [] intArray;
}
//public members here
private:
int* intArray;
};
Assuming the class allocates memory somehow for intArray, and then release it in the destructor, What if I used the class like this: MyClass* myClass = new MyClass(); and released it later with delete myclass;
How does delete handle the releasing of all the memory? Does the class destructor get called first to release all of the memory allocated by the class (ie int* intArray) and then release the memory allocated to hold the class?
What if I had a class like this:
class MyClass
{
public:
MyClass();
~MyClass()
{
delete anotherMyClass;
}
//public members here
private:
MyClass* anotherMyClass;
};
Assuming anotherMyClass is not allocated with the constructor, which would use up memory very quickly, what if there was a chain of MyClasses attached to each other like a linked-list? Would the delete statement in the destructor work in this case? Would each anotherMyClass be recursively released when the destructor gets called?
Are there any specific weird tricks or caveats with the new and delete statements that you know about?
Given a pointer (p) to a dynamically allocated object, delete does two things:
It calls the destructor of the dynamically allocated object. Note that when ~MyClass() completes, the destructors for any member variables of class type are called.
It frees the memory occupied by the dynamically allocated object.
It doesn't search the member variables of the object for other pointers to free; it doesn't free any other memory and doesn't do anything else.
If you need to free the memory pointed to by intArray, you need to delete it in the destructor of MyClass.
However, in almost all C++ code, you don't need to worry about this. You should be using smart pointers like shared_ptr, unique_ptr, auto_ptr, and scoped_ptr to automatically manage dynamically allocated objects. Manual resource management is difficult at best and should be avoided wherever possible.
This is part of a broader idiom, Scope-Bound Resource Management (SBRM, also called Resource Acquisition is Initialization, or RAII). This is by far the most important design pattern to understand and to use everywhere in your C++ code.
If in your class you had declared this instead:
boost::scoped_ptr<int> intArray;
then when the scoped_ptr<int> object is destroyed, it will free the pointer that it holds. You then do not have to do any work to manually destroy the object.
In well-written, modern C++ code, you should rarely need to manually use delete. Smart pointers and other SBRM containers should be used to manage any type of resource that needs cleanup, including dynamically allocated objects.
In your second example, given a linked list that looks like:
x -> y -> z -> 0
you would have an order of operations that looks like this:
delete x;
x.~MyClass();
delete y;
y.~MyClass();
delete z;
z.~MyClass();
delete 0;
[free memory occupied by z]
[free memory occupied by y]
[free memory occupied by x]
The objects in the linked list would be destroyed in reverse order.
delete intArray;
I assume intArray points to the first element of an int array? In that case, delete intArray yields undefined behavior. If you allocate via new[], you must release via delete[].
delete[] intArray;
Yes I know, delete intArray might appear to work just fine on certain systems with certain compiler versions under certain compiler options -- or it might not. That's undefined behavior for ya.
Also, you should follow the Rule of Three. Defining your own destructor but relying on the implicitly-defined copy constructor and copy assignment operator is a recipe for disaster.