だから、観た後この素晴らしい講義右辺値参照については、動的に割り当てられたメンバーがある場合、または一般的にポインターを格納する場合、Philipp が回答で指摘しているように、すべてのクラスがこのような「移動コンストラクタ」、template<class T> MyClass(T&& other)
編集、そしてもちろん「移動代入演算子」の恩恵を受けると考えました。前述の点が当てはまる場合は、コピーコンストラクタ、代入演算子、およびデストラクタが必要です。ご意見は?template<class T> MyClass& operator=(T&& other)
ベストアンサー1
3 つのルールは、3、4、5 のルールになると思います。
各クラスでは、次の特別なメンバー関数のセットの 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
};
少し面倒ですが、おそらく他の方法(この場合、移動の可能性がなく、コピーのみの特別なメンバー関数の自動生成)よりはましです。
ビッグ スリー ルールでは、ルールを順守しないと重大な損害が発生する可能性があるのに対し、ムーブ コンストラクターとムーブ代入演算子を明示的に宣言しないことは、通常は問題ありませんが、効率の点では最適ではないことがよくあります。前述のように、ムーブ コンストラクターとムーブ代入演算子は、明示的に宣言されたコピー コンストラクター、コピー代入演算子、またはデストラクタがない場合にのみ生成されます。これは、コピー コンストラクターとコピー代入演算子の自動生成に関する従来の C++03 の動作とは対称的ではありませんが、はるかに安全です。したがって、ムーブ コンストラクターとムーブ代入演算子を定義できる可能性は非常に便利であり、新しい可能性 (純粋に移動可能なクラス) が生まれますが、C++03 ビッグ スリー ルールに準拠したクラスでも問題ありません。
リソース管理クラスの場合、基になるリソースをコピーできない場合は、コピー コンストラクタとコピー代入演算子を削除済みとして定義できます (定義としてカウントされます)。多くの場合、移動コンストラクタと移動代入演算子は依然として必要です。コピー代入演算子と移動代入演算子は、swap
C++03 のように、 を使用して実装されることがよくあります。; について言えばswap
、移動コンストラクタと移動代入演算子が既にある場合、専門化するstd::swap
ジェネリックは移動コンストラクタと移動代入演算子を使用可能な場合は使用するため(そして、それは十分に高速であるはずなので)、これは重要ではなくなります。std::swap
リソース管理 (つまり、空でないデストラクタなし) またはサブタイプ多態性 (つまり、仮想デストラクタなし) を目的としていないクラスでは、5 つの特別なメンバー関数のいずれも宣言しないでください。これらはすべて自動生成され、正しく高速に動作します。