2012-05-26 4 views
22

私はとして与えられたコピーと移動コンストラクタの推奨署名を見てきました:コピーコンストラクタはconst参照を取得し、移動コンストラクタは非const右辺値参照を取る移動コンストラクタはconstまたは非const rvalue参照を取るべきですか?いくつかの場所で

struct T 
{ 
    T(); 
    T(const T& other); 
    T(T&& other); 
}; 

。例えば、以下の場合のように

限り私も見ることができるように、これは関数からのconstオブジェクトを返すときに、私は移動セマンティクスを利用して防ぐ、:

T generate_t() 
{ 
    const T t; 
    return t; 
} 

テストこのVC11ベータ版、T 'はコピーコンストラクタが呼び出され、移動コンストラクタは呼び出されません。 return std::move(t);を使用しても、コピーコンストラクタは引き続き呼び出されます。

私はtがconstのであるので、T&&に結合してはならないので、これは、理にかなっているかを見ることができます。 const T&&を移動コンストラクタのシグネチャで使用すると意味がありますが、otherがconstなので、メンバーをゼロにする必要がある場合、メンバをヌルにすることはできません。すべてのメンバスカラーであるか、正しいシグニチャーを持つコンストラクターを移動します。

tは、コンストラクタが一般的な場合に呼び出されて最初に非constになっていることを確認する唯一の方法ですが、それを行うのは嫌いです。 Tの顧客は、パフォーマンスを向上させるためにそのフォームに反対しなければならないことを知ることを期待していません。

私の質問は二重であると思います。最初に、移動コンストラクタはconstまたは非const rvalue参照を取るべきですか?そして2番目:私はこの推論のラインで正しいのですか?私はconstのものを返すのを止めるべきですか?

+2

まあ、私はconstの一時変数を返すユースケースはやや小さいと思います。あなたがそれを前もって宣言すれば、あなたはそれを返す前にいくつかのことをしたいからです。そうでなければ、とにかく単純な 'return T()'が行います。私はまだ特定のユースケースを見ることができますが、私はそれらがまれであると思います。そしてもちろん、あなたが資源を盗むことができない値の参照は、左辺の参照と比較して実際には価値がありません。しかし、質問を中断する。 –

+1

ところで、このコードはNRVOに適格ではありませんか?したがって、何が起こるべきかは、 'const'オブジェクト' t'が非const戻り値と同じ場所に構築されるということです。次に、必要であれば非const戻り値*を呼び出し元が非const移動コンストラクタ(または移動代入演算子)を介して移動できるようにします。しかし、構築の場合、コピー・エリジョンの資格があり、 'generate_t()'の呼び出しを使って初期化されているものに直接 't'を組み込むことができます。 VC11がこの最適化を妨げているのは何ですか? –

+1

_consting物事は良いですform_あなたを修正したい場合はありません。それらから移動することによって。 –

答えて

18

この値は、constの正の値でなければなりません。

オブジェクトは読み取り専用メモリに配置されている場合は、その正式な寿命がまもなく終了された場合でも、それからリソースを盗むことはできません。 C++でconstとして作成されたオブジェクトは、読み取り専用メモリに格納されます(const_castを使用して変更しようとすると、未定義の動作になります)。

+2

これは当てはまりません。移動できるオブジェクトは、リソースを管理していることを示しているため、オブジェクトが構築されたときに書き込み可能でなければならず、おそらくそれらのリソースを解放するデストラクタがあるため、破棄中に書き込み可能にする必要があります。私は、コンパイラが作成後にメモリページを読み取り専用としてマークし、破壊の前に書き込み可能にしておくことを管理するコードを生成するのではないかと疑う。 。)そうだ+1 +1 –

+0

@David: "私はそれを疑う..." - 本当ですが、それはデバッグモードでは有用な機能かもしれません。レガシーconst-incorrectコードを修正するとき。私は重要なことは、このことは実際には起こりませんが、デストラクタの前にconstオブジェクトを変更することができない理由が説明できるということです(特にリソースを保持する場所から効率的に移動できない) 。 –

+0

@SteveJessop:それが+1の理由です:オブジェクトが読み込み専用メモリ内にあるかどうかにかかわらず、定数オブジェクトからの移動が契約を破っているという事実は変わりません。タッチ。 –

8

移動コンストラクタは、通常、非const参照を取る必要があります。

constオブジェクトを移動することは可能だった場合、それは通常、それから「移動」にあったように、オブジェクトをコピーするなど効率的であったことを意味します。現時点では、通常、ムーブコンストラクタを使用する利点はありません。

また、あなたが潜在的にから移動したいしようとしている変数を持っている場合、それは非constする必要があることが正しいです。

私はそれを理解するように、これはスコット・マイヤーズは、C++ 11のための関数から値によってクラス型のオブジェクトを返すには彼のアドバイスを変更した理由です。 const修飾された値でオブジェクトを返すと、意図しない一時オブジェクトの変更が防止されますが、戻り値からの移動も禁止されます。

5

は移動コンストラクタはCONSTまたは非const右辺値参照を取るべきでしょうか?

non-const rvalue referenceとする必要があります。右辺値の参照は、まずconstフォームで意味をなさない(ある意味では、"移動"にしたい、あなたは自分の内部構造を望む)。

また、彼らはのconstなしを使用するように設計されていると私は、constの右辺値参照のためにのみ使用がスコット・マイヤーズがthis話に言及したことを非常に非常に難解なものであると信じています。

私はこの推論のラインにいますか?私はconstのものを返すのを止めるべきですか?

これはあまりにも一般的な質問の答えです。この文脈では、値と精度の両方を保持する機能があることを言及する価値はあると思います。また、渡されたものを返すべきであれば、通常の関数としての一時的な作成も避けられます。それ。

これは戻っても左辺値参照に「マングルされた」ことを右辺値参照を引き起こす、あなたは一般的に、前述の機能を持つため、完璧な転送は問題を解決し、することを望んでいません。

言われているように、私はあなたが単に私がリンクを投稿した話を見てみることをお勧めします。

関連する問題