简单程序:
#include <iostream>
using namespace::std;
class X {
public:
X() {
cout << "Default Constructor called\n";
i = 0;
}
X(int i) {
cout << "Parameterized Constructor called\n";
this->i = i;
}
X(const X& x) {
cout << "Copy Constructor called\n";
i = x.getI();
}
~X() {
cout << "Destructor called\n";
}
int getI() const {
return i;
}
X func() {
cout << "Entered func\n";
X x(2);
return x;
}
private:
int i;
};
int main() {
X x1;
X x2 = x1.func();
cout << "Returned from func\n";
}
输出以下内容:
Default Constructor called
Entered func
Parameterized Constructor called
Copy Constructor called
Destructor called
Returned from func
Destructor called
Destructor called
我的问题是,在打印'从func返回'之后,在创建实例x2时不会调用构造函数。我实际上期望在实例化x2时调用复制构造函数,就像我们做X x2 = x1;
答案 0 :(得分:2)
我最初错误地认为原因是RVO,所以我保留下面的原始答案。
您的程序打印预期。请注意,在调用之后打印“从功能返回”并将返回的值分配给x2
。因此打印的顺序是正确的:它首先实例化x
,因此参数化ctor调用,然后它将它复制到x2
,当它从函数退出时,然后它调用{{1}的析构函数},它不再需要,然后它实际上退出函数,然后才到达你的print语句。
旧答案如下
您观察到的是返回值优化。
返回值优化,或简称RVO,是编译器优化 涉及消除创建的临时对象的技术 保持函数的返回值。1在C ++中,它特别值得注意 允许更改结果的可观察行为 方案[2]
通常,C ++标准允许编译器执行任何操作 优化,只要生成的可执行文件展示相同 可观察的行为,好像(即假装)所有的要求 标准已经实现。这通常被称为 “as-if rule”。[3]术语返回值优化是指a C ++标准中的特殊条款甚至超过了 “as-if”规则:实现可能会省略复制操作 从return语句,即使复制构造函数有侧 的效果。[4]
请参阅this wikipedia article,它有一个与您非常相似的示例