Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: why it doesn't call a destructor?

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?

like image 279
JavaRunner Avatar asked Nov 29 '22 02:11

JavaRunner


2 Answers

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'?
like image 89
Mark Garcia Avatar answered Dec 05 '22 10:12

Mark Garcia


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.

like image 32
juanchopanza Avatar answered Dec 05 '22 09:12

juanchopanza