2017-07-04 93 views
3

的顺序我有以下C++代码(VS2013):C++ - 制造和破坏

#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)); 
} 

它产生以下输出:

DEFAULT CTOR 1

DEFAULT CTOR 3

DEFAULT CTOR 2

COPY CTOR 3

析构函数2

析构函数3

析构函数3

析构函数1

前3是参数构造(wrongfuly outputing “DEFAULT CTOR”,但没有按不要紧),在调用f之前调用它。

然后,当return *c;线路运行时,拷贝构造与值3运行,接着该对象的破坏与值2

最后,在main的范围的端部,将剩余物体(3,3,1)被破坏。

我不明白这种行为,没有找到任何解释。

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

具体来说:

  1. 为什么在第三对象&A(3)第二对象A(2)以前建造?这与他们的创作有什么关系(第三个是参照,第二个是价值),还是以f的方式定义(第二个是价值,第三个是指针)?

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

在此先感谢。

+6

你所说的“DEFAULT CTOR”是* not *默认的构造函数。可以使用* no *参数调用默认构造函数。 –

+8

至于你的第一个问题,没有指定参数的[评估顺序](http://en.cppreference.com/w/cpp/language/eval_order)。它可以是编译器想要的任何东西。 –

+0

有些程序员老兄,是的,你是对的。我现在将编辑我的帖子。 – Gil

回答

6

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

发生这种情况的原因是函数参数的求值顺序未被C++标准指定。编译器可以评估它们,但它喜欢。这是许多未定义行为实例的原因,当程序员不知道这一点时依赖于不存在的排序。

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

的种类,是的。 A(2)对象通过直接初始化函数f的参数来创建。函数参数的范围是函数的主体。所以A(2)在函数退出的时候超出了范围。其他对象的生命期稍长,因为它们是在函数之外创建的,并通过引用/指针传递。它们一直存在到完整表达式f(1, A(2), &A(3));的末尾,所以它们在后面被破坏。