web-dev-qa-db-ja.com

デフォルト/コピー/移動アクターおよびコピー/移動割り当て演算子の自動生成の条件は?

コンパイラーが通常、デフォルトのコンストラクター、コピーコンストラクター、および代入演算子を自動生成する条件で、メモリを更新します。

いくつかのルールがあったことを思い出しますが、覚えていないし、評判の良いリソースをオンラインで見つけることもできません。誰でも助けることができますか?

116
oompahloompah

以下では、「自動生成」とは、「デフォルトとして暗黙的に宣言されているが、削除済みとして定義されていない」ことを意味します。特別なメンバー関数が宣言されているが、削除済みとして定義されている場合があります。

  • ユーザーが宣言したコンストラクターがない場合、デフォルトのコンストラクターは自動生成されます(§12.1/ 5)。
  • ユーザーが宣言した移動コンストラクターまたは移動代入演算子がない場合、コピーコンストラクターは自動生成されます(C++ 03には移動コンストラクターまたは移動代入演算子がないため、これはC++ 03の「常に」に簡略化されます)( §12.8/ 8)。
  • コピー割り当て演算子は、ユーザーが宣言した移動コンストラクターまたは移動割り当て演算子がない場合に自動生成されます(§12.8/ 19)。
  • ユーザーが宣言したデストラクターがない場合、デストラクターは自動生成されます(§12.4/ 4)。

C++ 11以降のみ:

  • ユーザーが宣言したコピーコンストラクター、コピー割り当て演算子、またはデストラクターがない場合、および生成された移動コンストラクターが有効な場合(§12.8/ 10)、移動コンストラクターは自動生成されます。
  • 移動代入演算子は、ユーザーが宣言したコピーコンストラクタ、コピー代入演算子、またはデストラクタがなく、生成された移動代入演算子が有効な場合(たとえば、定数メンバーを割り当てる必要がない場合)に自動生成されます(§12.8/ 21)。
127
Philipp

下の図は非常に便利です。

C++ rules for automatic constructors and assignment operators from Sticky Bits-Zero Rule of Zero Hero

82
Marco M.

C++ 17 N4659標準ドラフト

クロス標準のクイックリファレンスについては、次のcppreferenceエントリの「暗黙的に宣言された」セクションを参照してください。

もちろん、標準から同じ情報を取得できます。例えば。 on C++ 17 N4659標準ドラフト

15.8.1「コンストラクタのコピー/移動」は、コンストラクタのコピーについて次のように述べています。

6クラス定義でコピーコンストラクターが明示的に宣言されていない場合、非明示的なコンストラクターが暗黙的に宣言されます。クラス定義が移動コンストラクターまたは移動代入演算子を宣言する場合、暗黙的に宣言されたコピーコンストラクターは削除済みとして定義されます。それ以外の場合は、デフォルト(11.4)として定義されます。後者のケースは、クラスにユーザーが宣言したコピー割り当て演算子またはユーザーが宣言したデストラクタがある場合は非推奨です。

移動コンストラクターの場合:

8クラスXの定義が移動コンストラクターを明示的に宣言していない場合、非明示的なコンストラクターは、次の場合にのみデフォルトとして暗黙的に宣言されます。

  • (8.1)— Xにはユーザーが宣言したコピーコンストラクターがありません。

  • (8.2)— Xにはユーザーが宣言したコピー割り当て演算子がありません。

  • (8.3)— Xには、ユーザーが宣言した移動代入演算子がありません。

  • (8.4)— Xにはユーザーが宣言したデストラクタがありません。

15.8.2「コピー/移動割り当て演算子」はコピー割り当てについて次のように述べています。

2クラス定義でコピー代入演算子が明示的に宣言されていない場合、コピー代入演算子が暗黙的に宣言されます。クラス定義が移動コンストラクターまたは移動代入演算子を宣言する場合、暗黙的に宣言されたコピー代入演算子は削除済みとして定義されます。それ以外の場合は、デフォルト(11.4)として定義されます。後者のケースは、クラスにユーザー宣言されたコピーコンストラクターまたはユーザー宣言されたデストラクタがある場合は推奨されません。

移動の割り当ての場合:

4クラスXの定義で移動代入演算子が明示的に宣言されていない場合、次の場合にのみデフォルトとして暗黙的に宣言されます。

  • (4.1)— Xにはユーザーが宣言したコピーコンストラクターがありません。
  • (4.2)— Xにはユーザーが宣言した移動コンストラクターがありません。
  • (4.3)— Xにはユーザーが宣言したコピー割り当て演算子がありません。
  • (4.4)— Xにはユーザーが宣言したデストラクタがありません。

15.4「デストラクタ」は、デストラクタに対して次のように述べています。

4クラスにユーザーが宣言したデストラクタがない場合、デストラクタは暗黙的にデフォルトとして宣言されます(11.4)。暗黙的に宣言されたデストラクタは、そのクラスのインラインパブリックメンバーです。