C++ドラフト状態:コピーの省略、一時バウンド・バイ・REFオブジェクト
12.8p31コピーの省略と呼ばれるコピー/移動操作のこのエリジオンは、に組み合わせることができる(以下の状況において許容されます)複数のコピーを排除:を参照(12.2)にバインドされていないことを、一時的なクラスのオブジェクトは/を移動、コピーされるだろう
(...)
- 0は、同じ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?
}
'StaticStuff :: send(y);'は実際に 'x'を間接的に変更する可能性を導入していません=>' MakeX'の終わりの後に 'x'への参照を使う未定義の動作です。 –
'おっと、私は清潔で新しい物を返すことを約束しましたが、実際には他の誰かによって静かに変更されるかもしれません。 'x'は' const X& 'ですので変更できません。 –
'MakeX'の2番目のバージョンはおそらくコピーコンストラクタを呼び出して' const X& 'を普通の' X'にします。 – didierc