我在代码中使用了额外的括号。我想当在局部变量范围结束后应该调用析构函数但它不能像这样工作:
class TestClass {
public:
TestClass() {
printf( "TestClass()\n" );
}
~TestClass() {
printf( "~TestClass()\n" );
}
};
int main() {
int a, b, c;
{
TestClass *test = new TestClass();
}
}
输出:
识别TestClass()
所以它不会调用TestClass的析构函数,但为什么呢?如果我手动调用它(删除测试),它会调用析构函数。但是为什么它不会在第一种情况下调用析构函数呢?
答案 0 :(得分: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 :(得分:8)
因为您有一个指向动态分配对象的指针。只有指针超出范围,而不是它指向的对象。你必须在指针上调用delete
,以便调用指针的析构函数。
尝试使用自动存储对象:
{
TestClass test;
}
这里,在退出范围时将调用析构函数。
不鼓励在C ++中使用原始指针来动态分配对象,因为它很容易导致资源泄漏,如代码示例中所示。如果确实需要指向动态分配对象的指针,那么使用smart pointer来处理它们是明智的,而不是试图手动处理它们的破坏。
答案 2 :(得分:1)
This answer足够好,但只是添加更多内容。
我发现您已使用Java
编码。在C++
中创建堆栈关键字new
中的变量/对象不是必需的。实际上,当您使用关键字new
时,您的对象在堆中创建,并且在离开范围后不会销毁。要销毁它,您需要在案例delete
delete test;
在你这样的结构中,在离开作用域后你只丢失指向对象的指针,所以在离开作用域之后你不能释放内存并调用析构函数,但最终OS在执行exit()
指令后调用析构函数。
总结C++
!= Java