2013-08-07 80 views
2

我在我的代码中使用了额外的括号。我想,当局部变量的作用域结束后析构函数应该叫,但它并没有这样的工作:C++:为什么它不调用析构函数?

class TestClass { 
public: 
    TestClass() { 
     printf("TestClass()\n"); 
    } 
    ~TestClass() { 
     printf("~TestClass()\n"); 
    } 
}; 

int main() { 
    int a, b, c; 
    { 
     TestClass *test = new TestClass(); 
    } 
} 

它输出:

识别TestClass()

所以它不调用TestClass的析构函数,但为什么?如果我手动调用它(删除测试),它会调用析构函数,对。但是为什么它不在第一种情况下调用析构函数?

+1

因为如果你创建了一个对象与'new',它只能调用'它delete'时破坏 - 它不会被走出去的范围被破坏。 – Nbr44

+2

@ Nbr44:不完全正确。你可以直接调用析构函数。当然,这不会释放内存,但会破坏对象。然后,没有未定义行为的情况下正确释放内存的唯一方法是在其位置构建另一个相同类型的对象(通过放置新的对象)并调用delete。 –

回答

12
TestClass *test = new TestClass(); 

您使用new创建一个动态分配的对象(最有可能放在堆上)。此类资源需要由您管理的手动。通过管理,完成使用后,您应该使用delete

{ 
    TestClass *test = new TestClass(); 
    // do something 
    delete test; 
} 

但是对于大部分的目的和意图的,你只需要使用自动存储对象,从而释放您不必手动管理对象的麻烦。它也很可能会有更好的表现,尤其是对于短命的对象。 除非你有充分的理由不这样做,否则你应该总喜欢使用它们。

{ 
    TestClass test; 
    // do something 
} 

但是,如果你需要动态分配对象的语义或指针,它总是会更好地使用一些机制来封装对象/资源对你来说,这也提供了删除/释放尤其是当您使用例外和条件分支时您更加安全。在你的情况下,如果你使用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) 
} 


以下是相关链接,以帮助你决定是否要使用自动存储对象或动态分配的对象: Why should C++ programmers minimize use of 'new'?

+1

“除非你有一个非常好的理由不这样做,否则你应该总喜欢使用它。” - 但为什么这里不使用指针非常重要?因为你可能忘记删除它或其他一些重要的原因? – JavaRunner

+1

@JavaRunner是的。而且他们最容易出错,会给你带来不必要的间接性,这可能会影响性能,而且在代码上加上大量的''''和''''''就很难看。 –

+2

@JavaRunner另外一个问题,除了阴云密布的生命周期外,还有一个问题:拥有一个指向动态分配对象的指针,也就是负责删除它的对象会变得很难。价值语义比引用语义更容易推理。 – juanchopanza

8

因为你有一个指向动态分配对象的指针。只有指针超出了范围,而不是它指向的对象。您必须在指针上调用delete才能调用指针的析构函数。

尝试用一个自动存储对象,而不是:

{ 
    TestClass test; 
} 

这里,析构函数被在离开范围调用。

在C++中使用原始指针来动态分配对象是不鼓励的,因为它很容易导致资源泄漏,如代码示例中所示。如果真的需要指向动态分配对象的指针,那么用smart pointer来处理它们是明智的,而不是试图手动处理它们的销毁。

1

This answer是不够好,但我想补充一些。

我看到你已经编码为Java。在C++中创建堆栈变量/对象关键字new不是必需的。其实当你使用关键字new你的对象是在堆中创建的,它不会在离开范围后破坏。要消灭它,你需要调用delete你的情况delete test;

在这样的结构是你的,剩下范围你只失去指针后所点到的对象,所以在离开范围后,将无法释放内存,并调用析构函数,但最终OS在执行exit()指令后立即调用析构函数。

综上所述C++ = Java

相关问题