使用指向对象的指针显式调用析构函数

时间:2014-03-26 17:43:56

标签: c++ oop destructor

不要在任何实现中使用,只是为了理解我试图使用对象和另一个*来对象显式调用析构函数。

CODE

#include<iostream>
using namespace std; 

class A{
public :
A(){
    cout<<"\nConstructor called ";
}

~A()
{
    cout<<"\nDestructor called ";
}
};

int main()
{
    A obj,*obj1;
    obj1->~A();
    obj.~A();
    return 0;
}


输出

output1


现在的问题是,我无法理解为什么析构函数被调用三次 即使obj1尚未指向任何对象 请注意,我知道最后两个析构函数调用是:

  1. 因为我打电话给obj.~A();
  2. 因为我们超出了对象obj的范围。
  3. 我正在使用DevC++ 5.5.1

4 个答案:

答案 0 :(得分:4)

您的代码仅适用于侥幸。

int main()
{   
    A obj,*obj1;
    obj1->~A(); // (1) Bad reference that works
    obj.~A();   // (2) Explicit call to destructor
    return 0;
} // (3) obj's destructor is called when obj goes out of scope

答案 1 :(得分:3)

obj1->~A();

您取消引用尚未初始化的指针obj1。这是未定义的行为

在这种情况下,任何事情都可能发生,没有任何保证。

答案 2 :(得分:1)

它被调用三次,两次显式,一次超出范围。

第一个显式调用无效,因为指针未初始化(这是未定义的行为)。在你的情况下,似乎无论如何都调用了析构函数,并且因为它没有使用this,所以没有任何不好的出现。 C ++标准中没有任何内容表明对未初始化指针的方法调用被忽略了!

通常,不应该多次调用对象的析构函数(显式或其他);但是,有明确的有效案例。考虑:

{
    alignas(alignof(A)) char data[sizeof(A)];    // Not an A object, so no
                                                 // call to dtor at scope end
    A* ptr = new (data) A();
    ptr->~A();    // object is now destructed but memory in `data` can be reused
}

答案 3 :(得分:0)

析构函数被调用3次的问题实际上非常简单。

在C ++中,堆栈上构造的对象在超出范围时会自动销毁。而必须明确删除用new分配的对象。

class MyClass
{
public:
    int Value;

    MyClass(int n) : Value(n) // initialize Value with n
    {
        cout << "MyClass::ctor(" << Value  << ")" << endl;
    }

    ~MyClass()
    {
        cout << "MyClass::dtor(" << Value << ")" << endl;
    }
};

int main()
{
    {
        MyClass a(10);                 // create a local object
        MyClass* b = new MyClass(20);  // create a dynamically allocated object

        delete b; // free dynamic memory and call destructor

    } // a goes out of scope and destructor is automatically invoked

    return 0;
}

所以这还没有真正回答你的问题。简单地说,没有办法避免自动销毁本地对象。解决方法是 Cameron 使用本地缓冲区和新位置的示例:

MyClass* a = new (buffer) MyClass(10); // use placement new on a sufficient buffer
a->~MyClass();                         // explicitly call destructor

如果您必须拥有本地显式对象,那么您始终可以跟踪您的对象是否确实有任何要销毁的内容:

class MyClass2
{
public:
    MyClass* Resource; // some resource we are managing

    MyClass2()      : Resource(nullptr)        {}
    MyClass2(int n) : Resource(new MyClass(n)) {}

    ~MyClass2()
    {
        if (Resource) // do we have anything to "destroy"?
        {
            delete Resource;    // call destructor, free memory
            Resource = nullptr; // ensure the resource is "destroyed" only once
        }
    }
};

所以实际上,如果确实有“破坏”的东西,它只会调用析构函数的“有用”部分。