1

我看过这个演示文稿,在幻灯片 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

4 回答 4

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

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

于 2013-10-26T18:16:58.467 回答
1

逻辑是

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

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

因此,您可以期望这些类的析构函数被调用的次数与创建这些类的次数相同。

于 2013-10-26T18:17:11.090 回答
1

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

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

于 2013-10-26T19:04:56.577 回答
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++ 切换到另一种,那么考虑这一点很重要,因为可能处理不同。

于 2013-10-26T18:35:59.140 回答