C++ 草案指出:
12.8p31 这种复制/移动操作的省略,称为复制省略,在以下情况下是允许的(可以结合起来消除多个副本):
(...)
- 当尚未绑定到引用(12.2) 的临时类对象将被复制/移动到具有相同 cv-unqualified 类型的类对象时,可以通过将临时对象直接构造到目标中来省略复制/移动操作省略的复制/移动
换句话说:
X MakeX() {
return X(); // Copy elided
}
X MakeX() {
const X& x = X(); // Copy not elided
return x;
}
限制引用的原因是什么?
请不要关注以下示例的有效性,因为它们只是为了说明我看不到临时和参考之间的区别(恕我直言)。
一方面,通过引入引用,我们允许其他对等方为同一个对象起别名,而调用者MakeX()
希望它是安全和干净的。
class Y {
public:
Y(const X& x) : _xRef(x) {}
private:
const X& _xRef;
};
X MakeX() {
const X& x = X();
Y y{x};
StaticStuff::send(y);
return x; // Oops, I promised to return a clean,
// new object, but in fact it might be silently
// changed by someone else.
}
但是这种情况呢(可能是 UB ;)):
class Y {
public:
Y(X* x) : _xPtr(x) {}
private:
X* _xRef;
};
X MakeX() {
X x;
Y y{&x}; // I'm referencing a local object but I know it will be
// copy elided so present in the outer stack frame.
StaticStuff::send(y);
return x; // Copy elided?
}