【问题标题】:c++ - order of construction and destructionc++ - 构造和销毁的顺序
【发布时间】:2017-12-07 14:11:22
【问题描述】:

我有以下 C++ 代码(VS2013):

#include <iostream>
using namespace std;
class A {
    int i;
public:
    A(int i) : i(i) {
        cout << "DEFAULT CTOR " << i << endl;
    }
    A(const A &o) : i(o.i) {
        cout << "COPY CTOR " << i << endl;
    }
    ~A() {
        cout << "DTOR " << i << endl;
    }
    friend A f(const A &, A, A *);
};
A f(const A &a, A b, A *c) {
    return *c;
}
int main() {
    f(1, A(2), &A(3));
}

它产生以下输出:

默认 CTOR 1

默认 CTOR 3

默认 CTOR 2

复制 CTOR 3

DTOR 2

DTOR 3

DTOR 3

DTOR 1

前 3 个是参数构造函数(错误地输出“DEFAULT CTOR”,但没关系),它们在调用 f 之前被调用。

然后,当return *c;行运行时,值3的复制构造函数运行,随后销毁值为2的对象。

最后,在main的作用域结束时,剩余的对象(3、3、1)被销毁。

我不理解这种行为,也找不到任何解释。

谁能详细说明事情发生的顺序?

具体来说:

  1. 为什么第三个对象&amp;A(3)在第二个对象A(2)之前构造?这和它们的创建有什么关系(第三个是引用,第二个是值),还是f的定义方式(第二个是值,第三个是指针)?

  2. return *c; 运行时,将创建第三个对象的副本以返回。 然后,唯一在返回之前被破坏的对象是第二个对象。再说一次,这与他们的创作有什么关系,还是与f 的定义方式有关?

提前致谢。

【问题讨论】:

  • 你所谓的“DEFAULT CTOR”不是默认构造函数。可以使用 no 参数调用默认构造函数。
  • 关于你的第一个问题,没有指定参数的evaluation order。它可以是编译器想要的任何东西。
  • 一些程序员老兄,是的,你是对的。我现在将编辑我的帖子。

标签: c++ constructor reference destructor


【解决方案1】:

为什么第三个对象 &A(3) 在第二个对象 A(2) 之前构造?这和它们的创建有什么关系(第三个是引用,第二个是值),还是f的定义方式(第二个是值,第三个是指针)?

这是因为 C++ 标准未指定函数参数的求值顺序。编译器可以根据自己的喜好评估它们。这是导致许多未定义行为实例的原因,当没有意识到这一点的程序员依赖于不存在的排序时。

当返回 *c;运行时,将创建第三个对象的副本以返回。然后,在返回之前被破坏的唯一对象是第二个对象。同样,这与它们的创建或定义 f 的方式有关吗?

有点,是的。 A(2) 对象是通过直接初始化函数f 的参数来创建的。函数参数的作用域是函数体。所以A(2) 在函数退出的那一刻就超出了范围。其他对象的生命周期稍长,因为它们是在函数外部创建的,并通过引用/指针传递。它们一直存在到完整表达式 f(1, A(2), &amp;A(3)); 的末尾,因此它们稍后会被销毁。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-02
    • 2016-03-25
    • 2013-01-19
    • 2013-08-13
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    相关资源
    最近更新 更多