离开作用域时没有调用析构函数
Destructor not being called when leaving scope
我正在学习c++中的内存管理,我不明白为什么只有一些析构函数在离开作用域时被调用。在下面的代码中,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 ;
}
这是我的析构函数:
cl1 :: ~cl1 () {
std::cout<< " cl1 destructor called"<<std::endl;
std::cout << this->data << std::endl; //just to identify the obj
delete [] str;
str = NULL ;
};
如果您使用new
分配对象
obj2= new cl1;
那么除非在它上面调用delete
,否则它的析构函数不会被隐式调用。
编辑:正如@David在注释中所说,可以显式地调用对象的析构函数,但根据我的经验,很少需要手动调用析构函数,除非使用放置new的新版本。
堆栈上的变量在作用域结束时被隐式清理(通过调用它们的析构函数)。
动态分配的对象不会被隐式清理,它是用户调用delete
显式清理它们的责任。这就是不应该使用原始指针而应该使用智能指针的原因。
动态分配的对象是你的责任 -你需要显式地清理它们。自动对象(如obj1
)在退出作用域时被清理,自动。在这种情况下,在退出作用域之前显式调用delete obj2
。注意:obj2 -> ~cl1
一行不做任何事情——delete
将负责正确触发析构函数。
obj1
是cl1
类型的对象,具有自动存储持续时间(它在堆栈上分配,其生存期由其所在的作用域决定)
obj1
是cl1*
类型的对象。也就是说,它是一个指针。指针也具有自动存储持续时间,但它所指向的对象没有。它指向自由存储区中动态分配的对象。
当您离开作用域时,具有自动存储持续时间的对象将被销毁。obj1
被销毁,调用析构函数。obj2
也被销毁,但是obj2
不是cl1
类型的,所以它不调用cl1
的析构函数。它是一个指针,当它被销毁时,它不会做任何特别的事情。
指针不拥有它们所指向的对象,因此它们不做任何事情来确保所指向的对象被销毁或清理。(如果你想要一个"拥有"的指针,这就是智能指针类的作用)
考虑你可以很容易地有多个指针指向同一个对象。
如果指针自动删除它所指向的对象,则会导致错误。两个不同指针所指向的对象会被删除两次。
obj2 -> ~cl1 ;
不要这样做!用delete obj2;
代替。
附录
你要做的是显式地调用析构函数。您的代码不会这样做。您的代码正在获取析构函数的地址,然后将其放入位桶中。你的代码是无操作的。显式调用析构函数的正确方法是obj2->~cli();
。
显式调用析构函数通常是不应该做的。
你应该做的是删除由new
创建的内存。正确的方法是使用delete
操作符。这会自动调用析构函数,并且释放内存。析构函数不释放内存。未使用delete导致内存泄漏。
当在堆栈上创建的对象超出作用域时,将自动调用析构函数。
对于动态分配的对象,需要调用delete obj
。Delete会自动为你调用析构函数。
对于动态分配的对象应该使用delete
:
delete obj2;
this调用析构函数并释放内存。你最好使用智能指针来管理这些对象——即使在new
和delete
之间抛出异常的情况下,它们也会为你调用delete
。
首先,您应该使用delete
操作符来销毁对象,而不是直接调用其析构函数。其次,通过做new
,你告诉编译器,你不想要删除对象时,它超出了作用域。在这种情况下,您需要显式地使用delete objj2;
来删除对象。
使用std::unique_ptr或std::shared_ptr代替原始指针。这是避免内存泄漏或双重释放的最好方法。
这在现代c++中是正确的。
int myfunc (cl1 *oarg)
{
cout << "myfunc called" << std::endl;
cl1 obj1(222,"NY");
std::unique_ptr<cl1> obj2( new cl1 );
oarg->disp();
}
- 什么时候调用析构函数
- C++-明确何时以及如何调用析构函数
- C++ 防止在映射中放置()时调用析构函数
- 调用析构函数以释放动态分配的内存
- C++:使用方法调用析构函数的顺序是什么?
- 向量推回调用析构函数时调用析构函数
- 如何在调用析构函数时优雅地停止/销毁带有阻塞调用C++线程?
- C++,我应该调用析构函数吗?
- 如何获取有关在 Clang LibTooling 中调用析构函数的信息?
- 当我从 std::vector 中的新放置调用析构函数时会发生什么?
- 为什么这里不调用析构函数
- 在调用 std::bind 的产品后意外调用析构函数
- 为什么在传递给函数而不是构造函数时调用析构函数?
- 如何在C++中调用析构函数
- 为什么为未删除的对象调用析构函数?
- 调用析构函数时出错
- C++ 在不释放内存的情况下调用析构函数
- 为什么在运算符删除中不调用析构函数?
- C++ 调用析构函数后动态模板队列"double free or corruption (out)"
- 在 postOrderDelete 上调用析构函数时引发的异常