为什么代码调用析构函数两次?

时间:2013-10-26 18:09:12

标签: c++ destructor

我看了this presentation,在幻灯片379,它显示了以下代码(稍作修改):

#include <iostream>
using namespace std;

struct A
{
    A() { cout << "A()" << endl; }
    A(int v) { cout << "A(int)" << endl; }
    ~A() { cout << "~A()" << endl; }
};

struct X
{
    X(int v) { a = v; }
    X(long v) : a(v) {}
    A a;
};

int main()
{
    cout << "bad style:" << endl;
    { X slow(int(2)); }
    cout << "good style:" << endl;
    { X fast(long(2)); }
}

输出是:

bad style:
A()
A(int)
~A()
~A()
good style:
A(int)
~A()

(此代码在我的机器上运行,用g ++编译)

现在,我理解为什么构造函数会以坏样式调用两次,但为什么析构函数会这样做呢?

4 个答案:

答案 0 :(得分:8)

X(int v) { a = v; }
//         ^^^^^

带下划线的行是作业。没有operator=需要intv),但是从intA的隐式转换。因此,构造A类型的临时对象并将其传递给编译器为您生成的赋值运算符。它会在以后被破坏(在完全表达它之后创建它)并且你有第二个析构函数你没想到。

答案 1 :(得分:1)

逻辑是

Instantiate a Class    ... +1 [Constuctor]
Desinstantiate a Class ... -1 [Destructor]

当该对象超出范围或被明确删除时,将为类对象调用析构函数。

所以你可以期望类的Destructors被调用这些类的次数相同。

答案 2 :(得分:1)

你成了“隐性类型转换”的受害者。尝试向构造函数添加“explicit”,并查看代码中的错误(它将停止在前一个隐式转换的位置进行编译):

struct A
{
    explicit A() { cout << "A()" << endl; }
    explicit A(int v) { cout << "A(int)" << endl; }
    ~A() { cout << "~A()" << endl; }
};

以下是解释: http://en.cppreference.com/w/cpp/language/implicit_cast

答案 3 :(得分:0)

<强>简介

在执行构造函数和执行时,还有一件事需要考虑。 C ++中的析构函数。

您是在声明静态分配对象还是动态分配对象?

静态分配

#include <iostream>
using namespace std;

class A {
public:
    // constructors
    A() { cout << "A()" << endl; }
    A(int v) { cout << "A(int)" << endl; }

    // destructors
    ~A() { cout << "~A()" << endl; }
};

class X {
public:
    // constructors
    X(int v) { a = v; }
    X(long v) : a(v) {}

    // variables
    A a;
};

int main()
{
    cout << "bad style:" << endl;
    X slow(int(2));

    cout << "good style:" << endl;
    X fast(long(2));
}

动态分配

#include <iostream>
using namespace std;

class A {
public:
    // constructors
    A() { cout << "A()" << endl; }
    A(int v) { cout << "A(int)" << endl; }

    // destructors
    ~A() { cout << "~A()" << endl; }
};

class X {
public:
    // constructors
    X(int v) { a = new(v); }
    X(long v) : { a = new(); *a = v; }

    // destructors
    ~X() { delete a; }

    // variables
    A* a;
};

int main()
{
    cout << "bad style:" << endl;
    X slow = new X(int(2));

    cout << "good style:" << endl;
    X fast = new (long(2));

    // do something else with "X"

    delete slow();
    delete fast();
}

<强>摘要

静态分配变量自动调用析构函数,而动态分配的变量使用指针,则需要显式调用析构函数。

**额外**

如果您以前使用过其他面向对象的语言,或者必须从C ++切换到另一种语言,这一点很重要,因为可能处理不同。