Destructor not being called when leaving scope

2019-02-11 07:29发布

问题:

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 ;

};

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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.



回答5:

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.



回答6:

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.



回答7:

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.



回答8:

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();
}