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


127

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

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

回答:


136

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

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

C ++ 11以降のみ:

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

9
継承されたデストラクタはカウントされますか?つまり、仮想デストラクタが空の基本クラスがあるとします。サブクラスでのmoveコンストラクターの作成を妨げますか?答えが「はい」の場合、基本クラスでmoveコンストラクターを定義すると役立ちますか?
kamilk 2014

10
constクラスにメンバーがあると、コンストラクターの自動生成が妨げられることをおそらく言及する必要があると思います...
nonsensickle 2014

「特別なメンバー関数が宣言されているが、削除済みとして定義されている状況があります。」たとえば、移動が不可能になるconstまたは参照メンバーがいる場所を参照しますか?いいえ、ありません。コピーが適用されるためです。
towi 2016

このフォーラムでハイパーリンクを送信することは制限されていることを知っています。しかし、それも良い記事です-cplusplus.com/articles/y8hv0pDG
bruziuz

標準では、クラスにユーザー宣言のコピー代入演算子またはユーザー宣言のデストラクタがある場合、暗黙的にデフォルト設定されたコピーコンストラクタは廃止されることに注意してください(12.8クラスオブジェクトのコピーと移動[class.copy])。
sigy

98

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

自動コンストラクターと代入演算子のC ++ルールスティッキービット から-ゼロヒーローのルールになる


綺麗な。「独立」とはどういう意味ですか?何から独立していますか?
towi 2016

8
コピートラクター/割り当ては、互いに「独立」しています。1つだけを記述する場合は、コンパイラがもう1つを提供します。対照的に、move ctorまたはmove割り当てのいずれかを指定した場合、コンパイラーはもう一方を提供しません。
Marco M.

コピー操作が独立している理由は何だろう。歴史的な理由かもしれませんか?または、コピーがターゲットを変更しないが移動するという事実は?
RaGa__M 2017

@Explorer_Nはい、下位互換性があるため、歴史的な理由があります。それはずっと前に悪い設計選択だったので、バグを見つけるのを難しくすることを避けるために、「3の法則」(3つすべてを定義するか、どれも定義しない:コピーコンストラクター、コピー代入演算子、そしてしばしばデストラクタ)のような良い実践の必要があります。
atablash 2018年

@MarcoM。、私が理解している限り、「記述した場合...」条件には、特殊メンバー関数を= delete(自明)または= default(自明ではない)に設定する2つのケースが含まれます。私は正しいですか?
エンリコマリアデアンジェリス

2

C ++ 17 N4659標準ドラフト

簡単な相互参照については、次のcppreferenceエントリの「暗黙的に宣言された」セクションをご覧ください。

もちろん、標準から同じ情報を取得できます。例: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)。暗黙的に宣言されたデストラクタは、そのクラスのインラインパブリックメンバーです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.