C++ ドラフトには次のように記載されています。
12.8p31 コピー省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます (複数のコピーを排除するために組み合わせることができます)。
(...)
- 参照 (12.2) にバインドされていない一時クラス オブジェクトが同じ cv 非修飾型のクラス オブジェクトにコピー/移動される場合、一時オブジェクトをターゲットに直接構築することにより、コピー/移動操作を省略できます。省略されたコピー/移動の
言い換えると:
X MakeX() {
return X(); // Copy elided
}
X MakeX() {
const X& x = X(); // Copy not elided
return x;
}
このような参照の制限の理由は何ですか?
次の例の有効性に焦点を当てないでください。一時的な参照と参照の違い (IMHO) が見当たらないことを例示するためのものです。
一方では、参照の導入により、他のピアが同じオブジェクトにエイリアスを設定できるようにしましたが、 の呼び出し元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?
}