简体   繁体   English

离开 scope 时未调用析构函数

[英]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.我在 C++ 中学习 memory 管理,但我不明白为什么在离开 scope 时只调用了一些析构函数。 In the code below, only obj1 destructor is called when myfunc ends, not for the dynamically allocated obj2.在下面的代码中,myfunc 结束时只调用了 obj1 的析构函数,而不是动态分配的 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如果您使用new分配 object

obj2= new cl1;

Then unless you call delete on it, its destructor won't be called implicitly.然后,除非您对其调用delete ,否则不会隐式调用其析构函数。

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.编辑:正如@David,评论中的意思,人们可能会明确调用 object 的析构函数,但根据我的经验,除非使用放置新版本的 new,否则很少需要手动调用析构函数。

Variables on stack are implicitly cleaned up(by calling their destructors) when their scope ends.当 scope 结束时,堆栈上的变量会被隐式清理(通过调用它们的析构函数)。

Dynamically allocated objects are not implicitly cleaned, it is the responsibility of the user to clean them up explicitly calling delete .动态分配的对象不会被隐式清理,用户有责任显式调用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 .自动对象(例如obj1 )在 scope 退出时被自动清理。 In this case, before the scope exits - explicitly call delete obj2 .在这种情况下,在 scope 退出之前 - 显式调用delete obj2 NOTE: this line obj2 -> ~cl1 - does not do anything - the delete will take care of triggering the destructor correctly.注意:这一行obj2 -> ~cl1 - 不做任何事情 - delete将负责正确触发析构函数。

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是一个cl1类型的 object ,具有自动存储持续时间(它在堆栈上分配,它的生命周期由它所在的 scope 决定)

obj1 is an object of type cl1* . obj1cl1*类型的 object 。 That is, it is a pointer .也就是说,它是一个指针 The pointer also has automatic storage duration, but the object it points to does not.指针也有自动存储持续时间,但它指向的 object 没有。 It points to a dynamically-allocated object in the free-store.它指向自由存储中动态分配的 object。

When you leave the scope, then the objects with automatic storage duration get destroyed.当您离开 scope 时,具有自动存储期限的对象将被销毁。 obj1 gets destroyed, calling your destructor. obj1被销毁,调用你的析构函数。 And obj2 also gets destroyed, but obj2 isn't of type cl1 , so it doesn't call cl1 's destructor.并且obj2也被销毁,但obj2不是cl1类型,因此它不会调用cl1的析构函数。 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.指针不拥有它们指向的对象,因此它们不会确保指向的 object 被销毁或清理。 (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.考虑到您可以轻松地让多个指针指向同一个 object。

If a pointer automatically deleted the object it pointed to, then that would lead to errors.如果指针自动删除了它所指向的 object,那么就会导致错误。 An object pointed to by two different pointers would get deleted twice.由两个不同指针指向的 object 将被删除两次。

obj2 -> ~cl1;

Don't do this!不要这样做! Use delete obj2;使用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();显式调用析构函数的正确方法是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 .您应该做的是删除由new创建的 memory 。 The correct way to do that is to use the delete operator.正确的方法是使用delete运算符。 This automatically calls the destructor and releases the memory.这会自动调用析构函数释放 memory。 The destructor does not release the memory.析构函数不会释放 memory。 Failing to use delete results in a memory leak.未能使用删除会导致 memory 泄漏。

Destructors are called automatically when an object that was created on the stack goes out of scope.当在堆栈上创建的 object 超出 scope 时,会自动调用析构函数。

With dynamically allocated objects, you need to call delete obj .对于动态分配的对象,您需要调用delete obj delete will automatically call your destructor for you. delete 会自动为你调用你的析构函数。

Use std::unique_ptr or std::shared_ptr instead of raw pointer.使用 std::unique_ptr 或 std::shared_ptr 而不是原始指针。 It the best way to avoid memory leaks or double free.这是避免 memory 泄漏或双重释放的最佳方法。

That is the right way in modern C++.这是现代 C++ 中的正确方法。

int myfunc (cl1 *oarg) 
{
    cout << "myfunc called" << std::endl;
    cl1 obj1(222,"NY");
    std::unique_ptr<cl1> obj2( new cl1 );
    oarg->disp();
}

You should use delete for dynamically allocated objects:您应该对动态分配的对象使用delete

delete obj2;

this calls the destructor and frees memory.这会调用析构函数并释放 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 .使用智能指针来管理这些对象会好得多——即使在newdelete delete

First of all you should use delete operator to destrory an object and not call its destructor directtly.首先你应该使用delete操作符来销毁 object 而不是直接调用它的析构函数。 Secondly, by doing new you are telling the compiler that you dont want to delete the object when it goes out of the scope.其次,通过执行new操作,您是在告诉编译器,当 object 超出 scope 时,您不想删除它。 In such case you need to explictly fo delete objj2;在这种情况下,您需要delete objj2; to delete the object.删除 object。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM