2017-06-21 6 views
26
struct copyable { // and movable 
    copyable() = default; 
    copyable(copyable const&) { /*...*/ }; 
    copyable& operator=(copyable const&) { /*...*/ return *this; } 
}; 

コピーコンストラクタおよびコピー代入演算関数は明示的に定義されているため、コンパイラによって暗黙的に移動コンストラクタおよび移動代入関数を定義できないため、移動操作は許可されません。抑制された移動構文/割り当てを持つ型は、引き続き移動可能とみなされますか?

上記の理解が正しいかどうか教えてください。

+3

移動は、元の変数を保存する必要がない特殊なケースと見ることができます。元の変数(コピーなど)を保持しても、移動は無効になりません。 – Bernard

+0

related/dupe:https://stackoverflow.com/questions/33939644/understanding-stdis-move-constructible – NathanOliver

+0

Bernardのコメントにもう少し詳しく説明する:移動後、ソース変数は必ず空であるとは限りません。 (いくつかのオブジェクトには "空"という概念もないかもしれません)。以前はターゲット変数(割り当ての場合)にあった値を持つことができました。std :: stringの場合は、移動前に長い文字列だった場合は空であることが多く、短い文字列だった場合は変更されません。 –

答えて

31

その移動のコンストラクタを意味し、割り当て機能を移動し、暗黙的にはいそうですコンパイラ

によって定義することはできません。

ですので、移動操作はできません。

右辺値は常にconst&にバインドされる可能性があるため、ノー、移動操作は、まだコピーコンストラクタを介して行うことができ、(これは、あなたが期待する場合ではないかもしれないが)代入演算子をコピーします。

さらに正確には、クラスcopyableは、まだMoveConstructibleMoveAssignableです。右辺値式をバインドすることができますconstのT &引数をとるコピーコンストラクタ:

クラスは、このタイプの要件を満たすために移動コンストラクタを実装する必要はありません。

MoveConstructibleクラスは移動のコンストラクタを実装している場合、それはまた、施工後のRVの値が指定されていないという事実を利用するために移動セマンティクスを実装することができます。

タイプがこのタイプの要件を満たすために、移動代入演算子を実装する必要はありません、値またはconst型&としてそのパラメータを取るコピー代入演算子を、バインドしますrvalue引数に。

MoveAssignableクラスが移動代入演算子を実装している場合、それはまた、譲渡後のRVの値が指定されていないという事実を利用するために移動セマンティクスを実装することができます。

@Curiousが指摘したように、あなたは移動コンストラクタを宣言し、copyableが移動不能にするために、明示的代入演算子deleteを移動することができます。 rvalue式を使用して、deleteの過負荷が選択され、コンパイルが失敗します。

+5

移動コンストラクタと代入演算子を明示的に削除すると、何が変更されるのかを言及する価値はあると思います。 – Curious

+2

@Curious Added。 – songyuanyao

+3

しかし、削除されていないコピーメンバと削除されていないコピーメンバとの結合は、クラスが 'CopyConstructible'と' CopyAssignable'必要条件(rvaluesからコピーする必要があります)を満たしていないため、ほとんど常に論理エラーです。例えば、ローカルの左辺値をファクトリ関数から値で返すことを禁止します。ガイドライン:移動メンバーを削除しないでください:https://stackoverflow.com/a/38820178/576911 –

関連する問題