C++ 98では、C++コンパイラは自動的にメンバーごとのコピーを介してコピーコンストラクタとコピー割り当て演算子を生成できます。
struct X {
std::string s;
std::vector<int> v;
int n;
};
コンパイラは自動的に、メンバーごとのコピーを使用して、X
のコピーコンストラクタとコピー割り当て演算子を生成します。
しかし、C++ 11では移動セマンティクスによってどのように変化するのでしょうか?
moveコンストラクターおよび move代入演算子自動的にコピーコンストラクタやコピー代入演算子のように生成されます?
移動操作が自動的に生成されない場合はありますか?
標準のChから。 12-特別会員機能
パー12.8 クラスオブジェクトのコピーと移動(私の強調)
9。クラスXの定義でmoveコンストラクターが明示的に宣言されていない場合、1つは、の場合に限り、デフォルトとして暗黙的に宣言されます。
— xには、ユーザーが宣言したコピーコンストラクターがありません。
— xには、ユーザーが宣言したコピー代入演算子がありません。
— xには、ユーザーが宣言したムーブ代入演算子がなく、
— xには、ユーザーが宣言したデストラクタがありません。
[注:moveコンストラクターが暗黙的に宣言されていないか、明示的に指定されていない場合、moveコンストラクターを呼び出す式は、代わりにcopyコンストラクターを呼び出す可能性があります。 —エンドノート]
次に11
デフォルトの移動コンストラクターを削除するためのルールを説明します
11。暗黙的に宣言されたコピー/移動コンストラクターは、そのクラスのインラインパブリックメンバーです。 Xが次の場合、クラスXのデフォルトのコピー/移動コンストラクターは削除済み(8.4.3)として定義されます:
—自明ではない対応するコンストラクターを持つバリアントメンバーであり、Xはユニオンのようなクラスです。
— Mの対応するコンストラクターに適用されるオーバーロード解決(13.3)により、あいまいさや関数が削除されたり、からアクセスできなくなったりするため、コピー/移動できないクラスタイプM(またはその配列)の非静的データメンバーデフォルトのコンストラクター、
— Bの対応するコンストラクターに適用されるオーバーロード解決(13.3)により、デフォルトのコンストラクターから削除またはアクセスできないあいまいさまたは関数が発生するため、コピー/移動できない直接または仮想の基本クラスB。
—デフォルトのコンストラクタから削除された、またはアクセスできないデストラクタを持つタイプの直接または仮想の基本クラスまたは非静的データメンバー、または、
—コピーコンストラクターの場合、右辺値参照型の非静的データメンバー。削除済みとして定義されているデフォルトの移動コンストラクターは、過負荷解決(13.3、13.4)によって無視されます。
[注:削除されたmoveコンストラクターは、代わりにcopyコンストラクターを使用できる右辺値からの初期化を妨害します。 —エンドノート]
ルールはやや圧倒される可能性があります。 複雑さを回避するには、いくつかの手法を使用することをお勧めします。例は次のとおりです。
*自分のコメントで指摘した点(1)と dyp (2)
Nikos Athanasiouは良い答えを出しましたが、私は非常に便利だと思うこのツールを追加したいと思いました。
これは、ハワード・ヒナントのプレゼンテーションのスクリーンショットです "移動セマンティクスについて知りたいと思ったことすべて(そしていくつか)" ACCU 2014会議から、自動生成のルールを非常によく思い出させると思います。特別会員:
コメントからのHinnant氏からの説明:
スライドにはそれが記載されていませんが、赤い四角は非推奨の動作を示しています。つまり非推奨の動作に依存したくない場合は、デストラクタを宣言する場合は両方のコピーメンバーを宣言するか、コピーメンバーの1つを宣言します(基本的にC++ 98/03の「ルール3」に従います)。
スライド を読んで、このテーブルの段階的な構成を取得し、これが現在どのように、なぜあるのかを詳細に説明することをお勧めします。
他のプレゼンテーションはそこにあります: http://accu.org/index.php/articles/1901