析构函数如何工作?

时间:2014-02-16 15:33:03

标签: c++ constructor

我想知道为什么我得到3x~C()。我知道前5个C()来自前2个声明,数组声明使用构造函数2次,然后是另一个声明。之后,为什么我得到3而不是1个析构函数调用?

#include <iostream>
    using namespace std;

    class C
    {
    public:
        C() {cout<< "C() ";}
        ~C() {cout<< "~C() ";}
    private:
        int i;
    };

    int main(){
        C c1;
        C* p1= new C;
        {
           C c[2];
           C* p2 = new C;  
           delete p2;
        }
        C c[2];
        delete p1;
        return 0;
    }
    //C() C() C() C() C() ~C() ~C() ~C() C() C() ~C() ~C() ~C() ~C()

5 个答案:

答案 0 :(得分:2)

我将分解代码并使用构造/销毁调用对其进行注释:

#include <iostream>
using namespace std;

class C
{
public:
    C() {cout<< "C() ";}
    ~C() {cout<< "~C() ";}
private:
    int i;
};

int main(){
    C c1; // C()
    C* p1= new C; // C()
    {
       C c[2]; // C() C() - because you constructed two C objects with this array
       C* p2 = new C;  // C()
       delete p2; // ~C()
    } // ~C() ~C() because the {} block ends, which means that local objects to that scope are destructed

    C c[2] ; // C() C() because you constructed two more
    delete p1; // ~C() because you're explicitly destructing
    return 0; // ~C() ~C() ~C() because of the c1 object and the c[2] array being destructed
}

所以最终会发生这种情况:

C() // c1 created
C() // p1 created
C() // c[2] created
C() // c[2] created
C() // p2 created
~C() // delete p2
~C() // c[2] in {} destroyed by end of scope
~C() // c[2] in {} destroyed by end of scope
C() // c[2] created
C() // c[2] created
~C() // delete p1
~C() // c[2] destroyed at end of program
~C() // c[2] destroyed at end of program
~C() // c1 destroyed at end of program

答案 1 :(得分:0)

删除对象指针时,或者当堆栈对象超出范围时,将调用析构函数。以下是您的代码中逐行发生的事情:

int main(){
    C c1;
    // C() (1 stack object created in main scope(a) )
    C* p1= new C;
    // C()
    {
       C c[2];
       // C() C() (2 stack objects created in inner scope)
       C* p2 = new C;  
       // C()
       delete p2;
       // ~C() 
    }
    // ~C() ~C() (the array of 2 objects went out of scope, so they got destructed)
    C c[2];
       // C() C() (2 stack objects created in main scope, (b) and (c))
    delete p1;
       // ~C() 
    return 0;
     // ~C() ~C() ~C() (3 stack objects destructed in main scope (a), (b) and (c))
}

如果您更改类以保留每个对象的唯一ID,则可以在此处了解更好的内容:

class C
{
public:
    C() 
    : i (newID()) {
      cout<< "C#" << i << "()";
    }
    ~C() {
       cout<< "~C#" << i << "()";
    }
private:
    int newID() {
         static int counter = 0;
         return counter++;
    }

    const int i;
};

输出:

  

C#0 C#1 C#2 C#3 C#4~C#4~C#3~C#2 C#5 C#6~C#1~C#6~C#5~C #0

答案 2 :(得分:0)

  1. C c1 ctr叫了1次
    • (ctr:1; dtr:0)
  2. C* p1= new C; ctr叫了1次
    • (ctr:2; dtr:0)
  3. C c[2]; ctr打了两次电话
    • (ctr:4; dtr:0)
  4. C* p2 = new C; ctr叫了1次
    • (ctr:5; dtr:0)
  5. delete p2; dtr叫了一次
    • (ctr:5; dtr:1)
  6. c超出范围,dtr调用2次
    • (ctr:5; dtr:3)
  7. C c[2]; ctr打了两次电话
    • (ctr:7; dtr:3)
  8. delete p1; dtr叫了一次
    • (ctr:7; dtr:4)
  9. c1超出范围; dtr叫1次
    • (ctr:7; dtr:5)
  10. c运行范围otu,dtr调用2次
    • (ctr:7; dtr:7)
  11. 现在,问题出在哪里?

答案 3 :(得分:0)

前5个构造函数调用是明确的。然后有3个析构函数调用。第一个c数组在块中声明:

{
   C c[2]
   //...
} // objects in c are destroyed

当剩下块时,通过调用它们的析构函数来销毁在块内非动态创建的所有对象。因此,有来自delete p2的第一个析构函数调用,然后是另外两个析构函数调用,用于销毁数组中包含的两个对象。对于最后的四个析构函数调用也是如此:第一个析构函数从您的delete p1调用os,其他三个析构函数调用是在块外声明的C c[2]并用于销毁{ {1}}对象。

答案 4 :(得分:0)

这可能有助于您理解任何非动态(malloc / new)堆分配对象超出范围时,它都会被销毁!

    #include <iostream>
    using namespace std;

    class C
    {
    public:
        C() {cout<< "C() ";}
        ~C() {cout<< "~C() ";}
    private:
        int i;
    };

    int main(){
        C c1; // Construct c1
        cout << "--------------";
        C* p1= new C; // Construct p1
        {
           cout << "--------------";
           C c[2]; // Construct 2 objects c[2]
           cout << "--------------";
           C* p2 = new C;  // Construct p2
           cout << "--------------";
           delete p2; // Destruct p2
        } // Destructs 2 objects c[2]
        cout << "--------------";
        C c[2]; // builds 2 objects
        cout << "--------------";
        delete p1;
        // p1 is destructed
        return 0;
    } // two objects in c[2] are destructed, c1 is also destructed

http://ideone.com/xlVUXm

输出:

C() --------------C() --------------C() C() --------------C() --------------
~C() ~C() ~C() --------------C() C() --------------~C() ~C() ~C() ~C()