在这段代码中:
#include <iostream>
using std::cout;
class Foo {
public:
Foo(): egg(0) {}
Foo(const Foo& other): egg(1) {}
int egg;
};
Foo bar() {
Foo baz;
baz.egg = 3;
return baz;
}
int main(void) {
Foo spam(bar());
cout << spam.egg;
return 0;
}
输出为3,而我预计为1.
这意味着在Foo垃圾邮件(bar())的行中没有调用复制构造函数.
我猜这是因为bar函数不返回引用.
你能解释一下垃圾邮件初始化时真正发生了什么吗?
如果这是一个愚蠢的问题,我提前道歉.
谢谢!
复制/移动elision是所谓的“as-if”规则唯一允许的异常,这通常限制了允许编译器对程序执行的变换(例如优化)的种类.
该规则旨在允许编译器执行任何希望的优化,只要转换的程序将工作“好像”是原来的.但是,有一个重要的例外.
根据C11标准第12.8 / 31段:
When certain criteria are met,an implementation is allowed to omit the copy/move construction of a class
object,even if the constructor selected for the copy/move operation and/or the destructor for the object
have side effects. […] This elision of copy/move operations,called copy elision,is permitted in the following circumstances (which
may be combined to eliminate multiple copies):
- in a
return
statement in a function with a class return type,when the expression is the name of a
non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified
type as the function return type,the copy/move operation can be omitted by constructing
the automatic object directly into the function’s return value
[…]
- when a temporary class object that has not been bound to a reference (12.2) would be copied/moved
to a class object with the same cv-unqualified type,the copy/move operation can be omitted by
constructing the temporary object directly into the target of the omitted copy/move
[…]
换句话说,在12.8 / 31条款适用的情况下,你不应该依赖于被调用或不被调用的构造函数或移动构造函数.