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



我看了一下这个演示文稿,在幻灯片 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++ 编译)

现在,我明白了为什么构造函数会在糟糕的样式中被调用两次,但是析构函数为什么要这样做呢?

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

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

逻辑是

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

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

因此,您可以预期类的析构函数将被调用相同的创建次数。

你成了"隐式类型转换"的受害者。尝试将"显式"添加到构造函数中,并查看代码中的问题(它将在前一个隐式转换的位置停止编译):

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

简介

在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++切换到另一种,那么考虑这一点很重要,因为处理方式可能不同。

最新更新