离开范围时不会调用析构函数

时间:2011-07-18 11:27:06

标签: c++ scope destructor

我正在学习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 ;

};

8 个答案:

答案 0 :(得分:6)

如果使用new

分配对象
obj2= new cl1;

然后,除非你在其上调用delete,否则不会隐式调用它的析构函数。

编辑:作为@David,注释中的含义,可以明确地调用对象的析构函数,但根据我的经验,除非使用新版本的新版本,否则很少需要手动调用析构函数。

当作用域结束时,会隐式清除堆栈上的变量(通过调用它们的析构函数)。

不会隐式清除动态分配的对象,用户有责任清除它们,并显式调用delete

这就是不应该使用原始指针但使用智能指针的原因。

答案 1 :(得分:2)

动态分配的对象您的责任 - 您需要显式清理它们。当示波器退出时,自动对象(例如obj1)将被清除,自动。在这种情况下,在范围退出之前 - 显式调用delete obj2。注意:这一行obj2 -> ~cl1 - 没有做任何事情 - delete将负责正确触发析构函数。

答案 2 :(得分:2)

obj1cl1类型的对象,自动存储持续时间(它在堆栈上分配,其生命周期由其所在的范围决定)

obj1cl1*类型的对象。也就是说,它是一个指针。指针也有自动存储持续时间,但它指向的对象没有。它指向免费存储中的动态分配对象。

当您离开范围时,具有自动存储持续时间的对象将被销毁。 obj1被破坏,调用你的析构函数。 obj2也会被销毁,但obj2不属于cl1类型,因此它不会调用cl1的析构函数。它是一个指针,当它被销毁时它没有什么特别的。

指针不拥有它们指向的对象,因此它们不会做任何事情来确保指向的对象被破坏或清理。 (如果你想要一个“拥有”指针,那就是智能指针类的用途)

考虑到您可以轻松地将多个指针指向同一个对象。

如果指针自动删除了它指向的对象,则会导致错误。两个不同指针指向的对象将被删除两次。

答案 3 :(得分:1)

  

obj2 -> ~cl1 ;

不要这样做!请改用delete obj2;

<强>附录
你要做的是明确地调用析构函数。您的代码不会这样做。您的代码获取析构函数的地址,然后将其放入位桶。你的代码是无操作的。显式调用析构函数的正确方法是obj2->~cli();

明确地调用析构函数通常是你不应该做的事情。

您应该删除new创建的内存。正确的方法是使用delete运算符。这会自动调用析构函数释放内存。析构函数不释放内存。未能使用删除会导致内存泄漏。

答案 4 :(得分:1)

当在堆栈上创建的对象超出范围时,会自动调用析构函数。

使用动态分配的对象,您需要调用delete obj。删除会自动为您调用析构函数。

答案 5 :(得分:0)

您应该使用delete来动态分配对象:

delete obj2;

这会调用析构函数并释放内存。使用智能指针管理此类对象会更好 - 即使在deletenew之间抛出异常,他们也会为您调用delete

答案 6 :(得分:0)

首先,你应该使用delete运算符来描述一个对象,而不是直接调用它的析构函数。其次,通过执行new,你告诉编译器你想要在它超出范围时删除它。在这种情况下,您需要明确地delete objj2;删除对象。

答案 7 :(得分:0)

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