简体   繁体   English

C ++:为什么不调用析构函数?

[英]C++: why it doesn't call a destructor?

I use extra brackets in my code. 我在代码中使用了多余的括号。 I thought when the destructor should be called after the local variable scope is ended but it doesn't work like this: 我以为应该在局部变量作用域结束后何时调用析构函数,但它不能像这样工作:

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

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

It outputs: 它输出:

TestClass() TestClass()

So it doesn't call the destructor of the TestClass but why? 所以它不调用TestClass的析构函数,但是为什么呢? If I call it manually (delete test) it calls the destructor, right. 如果我手动调用它(删除测试),它将调用析构函数。 But why it doesn't call the destructor in the first case? 但是,为什么在第一种情况下它不调用析构函数?

TestClass *test = new TestClass();

You using new which creates a dynamically allocated object (most likely placed on the heap). 您使用new创建一个动态分配的对象(最有可能放在堆中)。 This type of resource needs to be manually managed by you. 这种类型的资源需要由您手动管理。 By managing, you should use delete on it after you have done using it. 通过管理,使用完后应在其上使用delete

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

But for the most of your purposes and intents, you just have to use automatic-storage objects, which frees you the hassle of having to manually manage the object. 但是对于大多数目的和意图而言,您只需要使用自动存储对象即可,这使您不必手动管理对象。 It would also most likely to have better performance especially in short-lived objects. 它还最有可能具有更好的性能,尤其是在寿命短的对象中。 You should always prefer to use them unless you have a really good reason not to do so. 除非您有充分的理由不这样做,否则您应该始终喜欢使用它们。

{
     TestClass test;
     // do something
}

However, if you need the semantics of dynamically allocated objects or that of pointers, it will always be better to use some mechanism to encapsulate the deletion/freeing of the object/resource for you, which also provides you additional safety especially when you are using exceptions and conditional branches. 但是,如果您需要动态分配的对象或指针的语义,最好使用某种机制为您封装对象/资源的删除/释放,这也为您提供了额外的安全性,尤其是在使用时例外和条件分支。 In your case, it would be better if you use std::unique_ptr . 就您而言,最好使用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)
}


The following is a relevant link to help you decide whether to use automatic storage objects or dynamically allocated objects: Why should C++ programmers minimize use of 'new'? 以下是一个相关链接,可帮助您决定使用自动存储对象还是动态分配的对象: 为什么C ++程序员应尽量减少对“ new”的使用?

Because you have a pointer to a dynamically allocated object. 因为您有一个指向动态分配对象的指针。 Only the pointer goes out of scope, not the object it points to. 只有指针超出范围,而不是指针指向的对象。 You have to call delete on the pointer in order for the pointee's destructor to get called. 您必须在指针上调用delete才能调用被指针的析构函数。

Try with an automatic storage object instead: 请尝试使用自动存储对象:

{
  TestClass test;
}

Here, the destructor will be called on exiting the scope. 在这里,析构函数在退出范围时被调用。

The use of raw pointers to dynamically allocated objects in C++ is discouraged because it can easily lead to resource leaks like the one shown in your code example. 不建议在C ++中使用原始指针指向动态分配的对象,因为它很容易导致资源泄漏,如代码示例中所示。 If pointers to dynamically allocated objects are really needed, it is wise to handle them with a smart pointer , rather than to attempt to manually deal with their destruction. 如果确实需要指向动态分配对象的指针 ,明智的做法是使用智能指针处理它们,而不是尝试手动处理它们的破坏。

This answer is good enough but just to add some more. 这个答案已经足够好了,只是增加了一些。

I see you have been coded with Java . 我看到您已经使用Java进行了编码。 In C++ to create variable/object in stack keyword new is not needed. C++ ,不需要在堆栈中创建变量/对象关键字new Actually when you use keyword new your object is creating in heap and it doesn't destroys after leaving scope. 实际上,当您使用关键字new对象是在堆中创建的,并且在离开作用域后不会销毁。 To destroy it you need to call delete in your case delete test; 要销毁它,您需要在您的案例delete test;调用delete delete test;

In such a structure as yours, after leaving scope you just lose pointer what points into object, so after leaving scope you cannot free memory and call destructor, but eventually OS call destructor just after exit() instruction is executed. 在您这样的结构中,离开作用域后,您只会丢失指向对象的指针,因此,离开作用域后,您将无法释放内存并调用析构函数,但最终在执行exit()指令之后,OS会调用析构函数。

To sum up C++ != Java 总结C++ != Java

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

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