Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a destructor called when an object goes out of scope?

For example:

int main() {     Foo *leedle = new Foo();      return 0; }  class Foo { private:     somePointer* bar;  public:     Foo();     ~Foo(); };  Foo::~Foo() {     delete bar; } 

Would the destructor be implicitly called by the compiler or would there be a memory leak?

I'm new to dynamic memory, so if this isn't a usable test case, I'm sorry.

like image 855
Tux Avatar asked Jul 17 '13 14:07

Tux


People also ask

When should a destructor be called?

Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.

Is the destructor always called?

yes, when you delete something, the destructor is called.

When an object is destroyed or goes out of scope What type of member?

The destructor is only one way to destroy the object create by constructor. Hence destructor can-not be overloaded. Destructor neither requires any argument nor returns any value. It is automatically called when object goes out of scope.

Is a destructor called when the program ends?

If the program terminates gracefully the destructors are called to clean up . This can easily be observed either by attaching a debugger or putting a printf in the destructor.


2 Answers

Yes, automatic variables will be destroyed at the end of the enclosing code block. But keep reading.

Your question title asks if a destructor will be called when the variable goes out of scope. Presumably what you meant to ask was:

will Foo's destructor be called at the end of main()?

Given the code you provided, the answer to that question is no since the Foo object has dynamic storage duration, as we shall see shortly.

Note here what the automatic variable is:

Foo* leedle = new Foo(); 

Here, leedle is the automatic variable that will be destroyed. leedle is just a pointer. The thing that leedle points to does not have automatic storage duration, and will not be destroyed. So, if you do this:

void DoIt() {   Foo* leedle = new leedle; } 

You leak the memory allocated by new leedle.


You must delete anything that has been allocated with new:

void DoIt() {   Foo* leedle = new leedle;   delete leedle; } 

This is made much simpler and more robust by using smart pointers. In C++03:

void DoIt() {   std::auto_ptr <Foo> leedle (new Foo); } 

Or in C++11:

void DoIt() {   std::unique_ptr <Foo> leedle = std::make_unique <Foo> (); } 

Smart pointers are used as automatic variables, as above, and when they go out of scope and are destroyed, they automatically (in the destructor) delete the object being pointed to. So in both cases above, there is no memory leak.


Let's try to clear up a bit of language here. In C++, variables have a storage duration. In C++03, there are 3 storage durations:

1: automatic: A variable with automatic storage duration will be destroyed at the end of the enclosing code block.

Consider:

void Foo() {   bool b = true;   {     int n = 42;   } // LINE 1   double d = 3.14; } // LINE 2 

In this example, all variables have automatic storage duration. Both b and d will be destroyed at LINE 2. n will be destroyed at LINE 1.

2: static: A variable with static storage duration will be allocated before the program begins, and destroyed when the program ends.

3: dynamic: A variable with dynamic storage duration will be allocated when you allocate it using dynamic memory allocation functions (eg, new) and will be destroyed when you destroy it using dynamic memory allocation functions (eg, delete).

In my original example above:

void DoIt() {   Foo* leedle = new leedle; } 

leedle is a variable with automatic storage duration and will be destroyed at the end brace. The thing that leedle points to has dynamic storage duration and is not destroyed in the code above. You must call delete to deallocate it.

C++11 also adds a fourth storage duration:

4: thread: Variables with thread storage duration are allocated when the thread begins and deallocated when the thread ends.

like image 187
John Dibling Avatar answered Oct 12 '22 15:10

John Dibling


Yes, if an object goes out of scope, the destructor gets called. BUT No, the destructor won't be called in this case, because you only have a pointer in scope, that pointer has no particular destructor, so there will be no indirect call to Foo's destructor.

This example is the application domain of smart pointers like std::unique_ptr and std::shared_ptr. Those are actual classes that, unlike raw pointers have a destructor, (conditionally) calling delete on the pointed-to object.

Btw, Foo's destructor deletes bar, bur bar has never been initialized nor assigned to an address that points to an actual object, so the delete call will give undefined behavior, likely a crash.

like image 44
Arne Mertz Avatar answered Oct 12 '22 15:10

Arne Mertz