The difference between a destructor and 'delete' - c++

What is the difference between the destruction of an object and deletion in C++? In OOP, when an object goes out of the scope, the destructor is called, and when dynamically allocating memory we have to use the delete keyword inside the destructor. So what does it mean for an object to be destroyed or deleted?

A destructor is a special method for a class. It is called whenever an object goes out of scope, or someone calls it explicitly.
An example where an objects destructor is called, but no delete:
struct MyObject
{
MyObject() { std::cout << "default constructor"; }
~MyObject() { std::cout << "destructor"; }
void doWork() {};
}
int main()
{
{
MyObject object; //constructor is called and memory allocated for the object on the stack
object.doWork();
} //at the end of scope, the destructor of MyObject is called, and the stack memory is "released"
// object is not longer available and stack memory is free
}
An example when scope does not help you:
int main()
{
{
MyObject* object_ptr = new MyObject; //constructor is called and memory allocated on the heap. The pointer_ptr object
object_ptr->doWork();
} //at the end of scope the object_ptr is removed from the stack, but the destructor for the MyObject is not called!
// object_ptr is no longer available.
}
For the above example, we have an issue with the dynamically allocated memory. We explicitly call the destructor of the object we are pointing to by calling delete (and freeing the memory where MyObject is residing!):
int main()
{
{
MyObject* object_ptr = new MyObject; //constructor is called and memory allocated on the heap. The pointer_ptr object
object_ptr->doWork();
delete object_ptr; // destructor of MyObject is called and memory freed.
// object_ptr is still usable here, but it is pointing at an destroyed object, so don't use it! (unless you redirect it)
}
}
So delete is for managing the dynamic memory, but the destructor is a method of the class itself, which is always called when the object is getting freed from the memory (stack or heap). The destructor is called when freeing the memory for the object, so that if the object itself handles memory, is has time to release that memory. That's why smart pointers are good:
int main()
{
{
std::unique_ptr<MyObject> object_ptr = std::make_unique<MyObject>(); //constructor is called and memory allocated on the heap. The pointer_ptr object
object_ptr->doWork();
} //destructor for std::unique_ptr<MyObject> is called, which in turn calls delete on the object it is pointing at, which calls the destructor of that object!
}

There are multiple ways for memory allocation some of them are:
Automatic memory allocation :
In this case ,the variables defined inside a scope ,for example functions, are automatic allocated, and is usually stored on the stack. You have a limited control over the lifetime of this memory. E.g: automatic variables in a function are only there until the function finishes, then when going out of that scope, their destructors are called automatically i.e. you must not call delete to free the memory reserved for that object.
Dynamic memory allocation :
In this case , the variables defined inside a scope ,for example functions, are dynamically allocated. You control the size and the lifetime of these memory locations. If you don't free the reserved memory (delete it), the allocated memory is still valid and accessible, even though the function terminated (went out of scope) and in this case you'll have memory leakage, which may cause the program to crash. So the object should be delete explicitly which in turn will call the destructor for that object.

In the same way that a constructor is only part of the process of creating an object, invoking the destructor is just part of the process of destroying an object. It is a place where special clean-up code can go, like closing file handles or destroying other, indirectly-owned objects.
delete is the way you trigger the deletion of a dynamically allocated object. Other types of object are deleted automatically when they go out of scope. This keyword will clean up memory and more abstractly end the object's lifetime so that the compiler knows it doesn't conceptually "exist" any more.
You generally don't call the destructor manually, as it is usually insufficient for safely ending the lifetime of an object on its own. However, doing so is useful when you're taking super-fine-grained control over objects' existences, with (for example) placement new: then, it can be sufficient. But this is a special case.

When an object is destroyed it's destructor is called. A pointer to a dynamically allocated memory can be deleted, objects themselves can't be deleted (unless you think of a pointer as a kind of object).
Either of these actions can have knock on effects that cause the other action to happen (or more instances of the same action). For instance if you delete a pointer to an object, then the objects destructor will be called (if it has one) and it's destructor may cause other pointers to be deleted and other objects to be destroyed.
Basically destructor is about the death of objects and deletion is about the freeing of dynamically allocated memory, but the two actions are often intertwined.

Related

Calling destructor to free dynamically allocated memory

Let consider this code:
#include <iostream>
class A{
public:
~A() {}
};
int main(){
A *p = new A();
p->~A();
return 0;
}
I would like to know if the memory of the object A pointed by p is freed or we must to call delete p;
The memory was not freed. The destructor destroys the object but does not free the memory. How could it? You can destroy objects that are dynamically allocated, are on the stack, are globals, and so on. The destructor has no idea what is needed, if anything, to release the memory.
Memory was allocated using operator new and will be freed (deallocated) using operator delete, not your object's destructor.
We should not confuse the object lifetime with dynamic memory management.
It is not A's destructor role to free the allocated memory and it should not be called explicitly. It is simply a member function that gets called when your object gets destroyed. And it will get destroyed after you call the delete.
Replace:
p->~A();
with:
delete p;
Now your objects gets destroyed and the allocated memory gets deallocated.
There is no difference between calling destructor or any other member function, except one thing - you should not do it, unless you want to separate object allocation from its construction and destruction.

Why not call Destructor in C++?

I studding C++ concept. I'm confused in constructor and Destractor concept. Destructor will be invoked implicitly by the compiler upon exit from the program. But in my program, only constructor called.
#include <iostream>
using namespace std;
class A
{
int i;
public:
A()
{
cout<<"Constructor call"<<endl;
}
~A()
{
cout<<"Destructtor call"<<endl;
}
};
int main()
{
A *a = new A();
}
Output:
Constructor call
So, I have question : Why destructor not call implicit by the compiler upon exit program?
Why destructor not call implicit by the compiler upon exit program?
Because dynamically allocated objects are not destroyed automatically. That is how the language has been specified. Tracking the destruction of dynamic objects would require runtime / memory overhead.
Solution: Do not leak dynamically allocated objects.
There are 2 "types" of variable lifetime in C++. Dynamic and automatic.
Automatic is something like :
void foo()
{
int i; // automatic storage
} // destroys i
Here, i will be destructed the moment it leaves scope (after foo returns). You can check this for yourself by making your object have an automatic lifetime:
int main()
{
A a; // calls A's constructor and allocates memory.
} //calls A's destructor and frees the memory used.
You'll see that both the constructor and the destructor will get called.
The second form is dynamically allocated memory. You can dynamically allocate memory by using new (like you did) and free that memory by using delete. The compiler won't do this for you.
This means that, to destruct your object you have to call delete explicitly yourself:
int main()
{
A* a = new A();
delete a; // calls A's destructor and frees the memory used.
}
If you do not call delete (like your code) then the moment the program leaves main the pointer a is destroyed and now we have a piece of memory that nothing can reach and thus nobody can clean up (with delete) which means you're leaking memory.
However, modern operating systems reclaim all memory used by the program automatically the moment the program ends so at this point it won't matter too much. This does mean your destructor won't be called as you've just witnessed.
Dynamically allocated memory allows you to do some nifty tricks like controlling the lifetime of your objects to the point where you want to destroy them explicitly yourself with delete. The problem with using new and delete is that it's so easy to forget a single delete and your program will already leak memory, which is why it's advised to stay away from this way of allocation.
If for some reason you absolutely need dynamic lifetime then use a smart pointer like std::unique_ptr that will call new and delete for you the moment it goes out of scope.
You create the object dynamically with new. The destructor will only be called when the objected is deleted with delete.
To prevent memory leaks, you could/should use smart pointers like unique_ptr.
In any case, the memory itself will of course be released when the process ends.
The destructor is never called in your code because the object is never destroyed.
You dynamically allocate the A object and you never deallocate it. Add delete a; into main() and you'll see the destructor in action:
int main()
{
A *a = new A();
delete a;
return 0;
}
In your main function, you create a pointer variable that you must delete it by delete a at end of main function.
Because you have a memory leak. You dynamically created an object with new, promising that you would manage the lifetime of the object and clean it up later with delete. Then you broke that promise.
If you create an object in the usual fashion:
A a;
then it will be destroyed automatically for you.

If I make objects inside a method in c++, will they get automatically destroyed when the function returns, or will it continue to eat memory?

void Player::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
sf::CircleShape c0;
c0.setFillColor(sf::Color::Red);
c0.setPointCount(4);
c0.setRadius(1);
c0.setPosition(sf::Vector2f(point[0].x, point[0].y));
sf::CircleShape c1;
c1.setFillColor(sf::Color::Red);
c1.setPointCount(4);
c1.setRadius(1);
c1.setPosition(sf::Vector2f(point[1].x, point[1].y));
target.draw(c0);
target.draw(c1);
}
I am learning c++. As you can see I am making the CircleShape objects inside the draw method which runs at 60 times in a second. I read online that objects in c++ are stored in heap memory therefore require manual deallocation. Do the objects c0 and c1 get destroyed and the memory frees when draw method returns, or will they continue to eat heap memory ?
When you declare variables on the stack, their destructors will get called when they fall out of scope
{
int a = 5;
}
// a is now out of scope, it's destructor was called
You would have to go out of your way to clean up the memory if you allocated from the heap
{
int* a = new int(5);
}
// a was just leaked, unless you had a pointer to it later
You would have to have cleaned it up like
{
int* a = new int(5);
delete a;
}
As of C++11, I would strongly advocate for using <memory> if you need heap allocated memory, but still want RAII cleanup.
#include <memory>
{
std::unique_ptr<int> a = std::make_unique<int>(5);
}
// a falls out of scope, the unique_ptr ensures the memory is cleaned up
The code you wrote only creates temporary objects on the stack, which are destroyed when the method exits.
In general, when your variables go out of scope, their content is no longer available.
If you allocate memory using the "new" keyword, then your objects will be kept in memory, but the pointer is lost when the variable referencing them goes out of scope.
Edit:
Actually, "temporary objects" are a feature of the C++ language, which can cause headaches if not used correctly. Read more here: Temporary objects - when are they created, how do you recognise them in code?
The objects you create as local variables inside a function are automatically allocated and destroyed, I only used the word "temporary" to describe their behaviour: they are discarded when the function exits.
Do the objects c0 and c1 get destroyed and the memory frees when draw method returns,
Yes. They get destroyed when the function returns.
or will they continue to eat heap memory ?
The answer to that depends on what you do in the constructor and the destructor of the class. If you allocate memory from heap in the constructor or any of the other member function, that memory should be freed in the destructor. Otherwise, your function will leak memory, indirectly.

At what moment is an object exactly "created"?

Let's say we have some class with a constructor:
class MyClass
{
public:
MyClass()
{
//our code goes here
throw "OMG";//well, some code that throws an exception
}
};
Now, when an exception occurs, stack unwinding is being performed. I also know that if the exception is thrown from the constructor, the corresponding object's destructor will not be called, because the object was never completely "created" in the first place.
I'm a little confused by this. To me that implies that the object is considered "created" only when the constructor finishes. But obviously, all the memory is allocated at some place before (or right after) the constructor is called, because we can manipulate the object's members inside the constructor.
So when exactly is the object created in memory, and what happens to the memory of an object that caused the exception?
The memory is allocated before the body of the constructor.
If a constructor fails, the automatically allocated memory is freed.
And the accent of "automatically allocated" is important - if you have dynamically allocated memory in the constructor and the constructor fails (for example, you may have used new before throw "OMG"), this memory will leak.
That's because - you have allocated this memory, you need to free it.
You're right, that the destructor is not called, but the destructor is not the one, which frees the memory, allocated for the auto members of a class.
It's used (basically) to free memory, allocated by the user (in the constructor or somewhere else).
In other words, allocating memory for an object is different from the object's construction.
Another example - if you create an object dynamically, like:
MyObj* = new MyObj;
this will:
call operator new
then call the constructor of MyObj
See, both things are different.
Memory allocation and object construction are two separate things in C++. The compiler just makes sure that when thay're invoked together (which is the case with the regular - i.e., non-placement - new operator) and construction fails, the allocation is reverted.
Also, when the class has sub-objects (base classes and/or fields), the compiler invokes their constructors in a fixed order and makes sure than when one of them throws, the already-constructed sub-objects are disposed of properly (i.e., have their destructors called).
The memory of the object is freed, but the destructor is not called (hence e.g. dynamically allocated pointers created within the constructor are not freed if you do not handle the exception in the constructor correctly). In C++11 the spec says that the destructor is called if and only if one constructor has completed entirely (relevant since a constructor can refer to another constructor).
Example (memory allocated by new int () is not freed):
struct Broken {
int * i;
Broken () {
i = new int {5};
OperationCausingException ();
}
~Broken {
delete i;
}
}
try {
Broken * b = new Broken {};
} catch (...) {
}
// memory leak: *b is freed, but b->i still exists

Destructor not being called when leaving scope

I am learning memory management in C++ and I don't get the why only some of the destructors are called when leaving scope. In the code below, only obj1 destructor is called when myfunc ends, not for the dynamically allocated obj2.
int myfunc (cl1 *oarg) {
cout << "myfunc called" << std::endl;
cl1 obj1(222,"NY");
cl1 *obj2;
obj2= new cl1;
oarg->disp();
obj2 -> ~cl1 ;
}
Here is the destructor I have :
cl1 :: ~cl1 () {
std::cout<< " cl1 destructor called"<<std::endl;
std::cout << this->data << std::endl; //just to identify the obj
delete [] str;
str = NULL ;
};
If you allocate a object using new
obj2= new cl1;
Then unless you call delete on it, its destructor won't be called implicitly.
EDIT: As #David, meantions in comments, One may call destructor of an object explicitly but in my experience there is rarely a need to manually call the destructor unless one is using placement new version of new.
Variables on stack are implicitly cleaned up(by calling their destructors) when their scope ends.
Dynamically allocated objects are not implicitly cleaned, it is the responsibility of the user to clean them up explicitly calling delete.
This is the very reason one should not use raw pointers but use smart pointers.
Dynamically allocated objects are your responsibility - you need to explicitly clean them up. Automatic objects (such as obj1) are cleaned up when the scope exits, automatically. In this case, before the scope exits - explicitly call delete obj2. NOTE: this line obj2 -> ~cl1 - does not do anything - the delete will take care of triggering the destructor correctly.
obj1 is an object of type cl1, with automatic storage duration (It is allocated on the stack, and its lifetime is determined by the scope it is in)
obj1 is an object of type cl1*. That is, it is a pointer. The pointer also has automatic storage duration, but the object it points to does not. It points to a dynamically-allocated object in the free-store.
When you leave the scope, then the objects with automatic storage duration get destroyed. obj1 gets destroyed, calling your destructor. And obj2 also gets destroyed, but obj2 isn't of type cl1, so it doesn't call cl1's destructor. It is a pointer, and it does nothing special when it is destroyed.
Pointers don't own the objects they point to, and so they do nothing to ensure the pointed-to object gets destroyed or cleaned up. (If you want an "owning" pointer, that's what smart pointer classes are for)
Consider that you can easily have multiple pointers pointing to the same object.
If a pointer automatically deleted the object it pointed to, then that would lead to errors. An object pointed to by two different pointers would get deleted twice.
obj2 -> ~cl1 ;
Don't do this! Use delete obj2; instead.
Addendum
What you were trying to do was to call the destructor explicitly. Your code does not do that. Your code is getting the address of the destructor and then dropping it into the bit bucket. Your code is a no-op. The correct way to explicitly call the destructor is obj2->~cli();.
Explicitly calling the destructor is usually something you should not do.
What you should do is to delete the memory created by new. The correct way to do that is to use the delete operator. This automatically calls the destructor and releases the memory. The destructor does not release the memory. Failing to use delete results in a memory leak.
Destructors are called automatically when an object that was created on the stack goes out of scope.
With dynamically allocated objects, you need to call delete obj. delete will automatically call your destructor for you.
You should use delete for dynamically allocated objects:
delete obj2;
this calls the destructor and frees memory. You'll be much better off using smart pointers for managing such objects - they will call delete for you even in case of exception being thrown between new and delete.
First of all you should use delete operator to destrory an object and not call its destructor directtly. Secondly, by doing new you are telling the compiler that you dont want to delete the object when it goes out of the scope. In such case you need to explictly fo delete objj2; to delete the object.
Use std::unique_ptr or std::shared_ptr instead of raw pointer.
It the best way to avoid memory leaks or double free.
That is the right way in modern C++.
int myfunc (cl1 *oarg)
{
cout << "myfunc called" << std::endl;
cl1 obj1(222,"NY");
std::unique_ptr<cl1> obj2( new cl1 );
oarg->disp();
}