1. ホーム
  2. c++

[解決済み] C++11でRule-of-ThreeがRule-of-Fiveに?[クローズド]

2022-03-17 16:44:33

質問

で、見終わって この素晴らしい講演は このようなコンストラクタは、どのクラスにも必要なものだと思います。 template<class T> MyClass(T&& other) 編集 そしてもちろん、"移動代入演算子" もあります。 template<class T> MyClass& operator=(T&& other) Philippの回答で指摘されているように、動的に割り当てられるメンバーがある場合、あるいは一般的にポインターを保存している場合です。ちょうど、あなたが べきである には、コピーベクトル、代入演算子、デストラクタがあります。 いかがでしょうか?

どのように解決するのですか?

三の法則が三・四・五の法則になるんですね。

<ブロッククオート

各クラスは、明示的に1つだけ定義する必要があります。 以下の特別なメンバー 関数があります。

  • なし
  • デストラクタ、コピーコンストラクタ、コピー代入演算子

また、デストラクタを明示的に定義した各クラスは、移動コンストラクタおよび/または移動代入演算子を明示的に定義することができます。

通常、以下の特別なメンバのセットのいずれかを使用します。 関数が賢明である。

  • なし(暗黙的に生成される特殊なメンバ関数が正しく、高速な多くの単純なクラスの場合)
  • デストラクタ、コピーコンストラクタ、コピー代入演算子(この場合 クラスは移動できない)
  • デストラクタ、移動コンストラクタ、移動代入演算子(この場合、クラスはコピー不可となります。)
  • デストラクタ、コピーコンストラクタ、コピー代入演算子、移動コンストラクタ(コピーエリジョンのため、コピー代入演算子が引数を値で取る場合はオーバーヘッドがない)
  • デストラクタ、コピーコンストラクタ、コピー代入演算子、移動コンストラクタ。 移動代入演算子

  • 他の特殊なメンバ関数(デストラクタ、コピーコンストラクタ、移動代入演算子など)を明示的に宣言しているクラスでは、移動コンストラクタと移動代入演算子は生成されないということです。
  • 移動コンストラクタや移動代入演算子を明示的に宣言しているクラスでは、コピーコンストラクタやコピー代入演算子は生成されないということです。
  • また、明示的にデストラクタが宣言され、暗黙的にコピーコンストラクタまたは暗黙的にコピー代入演算子が定義されているクラスは非推奨と見なされることです。

特に、以下のような完全に有効なC++03ポリモーフィック基底クラスがあります。

class C {
  virtual ~C() { }   // allow subtype polymorphism
};

以下のように書き換える必要があります。

class C {
  C(const C&) = default;               // Copy constructor
  C(C&&) = default;                    // Move constructor
  C& operator=(const C&) = default;  // Copy assignment operator
  C& operator=(C&&) = default;       // Move assignment operator
  virtual ~C() { }                     // Destructor
};

少し面倒ですが、おそらく代替案(この場合は、コピーするための特別なメンバー関数を自動生成する)よりはましでしょう。 のみ 移動の可能性なし)。

ルールを守らないと大変なことになるビッグ3のルールとは対照的に、移動コンストラクタと移動代入演算子を明示的に宣言しないことは、一般的には問題ありませんが、効率性に関しては最適でないことが多いです。前述のように、移動コンストラクタと移動代入演算子は、明示的に宣言されたコピーコンストラクタ、コピー代入演算子、デストラクタが存在しない場合にのみ生成されます。これは、コピー コンストラクタとコピー代入演算子の自動生成に関する従来の C++03 の動作と対称的ではありませんが、より安全です。したがって、移動コンストラクタと移動代入演算子を定義できることは非常に便利であり、新しい可能性(純粋に移動可能なクラス)が生まれますが、C++03 のビッグ 3 規則に準拠したクラスでも問題はありません。

リソース管理クラスでは、基礎となるリソースをコピーできない場合、コピーコンストラクタとコピー代入演算子を削除済みとして定義できます(これは定義としてカウントされます)。多くの場合、移動コンストラクタと移動代入演算子はまだ必要です。コピーと移動の代入演算子は、しばしば swap C++03と同様です。C++03のように swap もし、すでにムーブコンストラクタとムーブアサイン演算子があるのなら。 専門化 std::swap になります。 重要でない というのは、一般的な std::swap は、利用可能であれば、move-constructor と move-assignment 演算子を使用します(それで十分速くなるはずです)。

リソース管理を目的としないクラス(つまり、空でないデストラクタがない)やサブタイプ多相性(つまり、仮想デストラクタがない)は、5つの特別なメンバー関数のどれも宣言してはいけません:それらはすべて自動生成され、正しく、高速に動作します。