c ++ - 构造和破坏的顺序

Gil*_*Gil 3 c++ constructor destructor reference

我有以下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));
}
Run Code Online (Sandbox Code Playgroud)

它产生以下输出:

DEFAULT CTOR 1

DEFAULT CTOR 3

DEFAULT CTOR 2

COPY CTOR 3

DTOR 2

DTOR 3

DTOR 3

DTOR 1

前3个是参数构造函数(错误输出"DEFAULT CTOR"但无关紧要),它们在调用之前调用f.

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

最后,在main范围的最后,剩余的对象(3,3,1)被破坏.

我不明白这种行为,并没有找到解释.

任何人都可以详细说明发生的事情的顺序吗?

特别:

  1. 为什么&A(3)在第二个对象之前构造第三个对象A(2)?这是否与它们的创建有关(第三个是通过引用,第二个是按值),或者f是定义了方式(第二个是按值,第三个是指针)?

  2. return *c;运行时,创建了第三个对象的副本归还.然后,在返回之前被破坏的唯一对象是第二个对象.同样,这与他们的创作有关,还是f定义了方式?

提前致谢.

Sto*_*ica 6

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

之所以发生这种情况,是因为C++标准没有指定函数参数的评估顺序.编译器可以根据需要对它们进行评估.这是许多未定义行为实例的原因,当不知道这种情况的程序员依赖于不存在的排序时.

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

是的,是的.该A(2)物体是由函数参数的直接初始化创建f.函数参数的范围是函数体.因此A(2)功能退出的时刻就超出了范围.其他对象的生命周期稍长,因为它们是在函数外部创建的,并通过引用/指针传递.它们存在直到完整表达式结束f(1, A(2), &A(3));,因此它们将在以后被破坏.