1

三つのルール(ビッグスリーの法則またはビッグスリーとも呼ばれます)は、C ++の経験則であり、クラスが次のいずれかを定義する場合、デストラクタ、コピーコンストラクタ、コピー代入演算子。

デフォルト以外のコンストラクターがそれらの1つと見なされないのはなぜですか?クラスで管理されているリソースがある場合、プログラマーはとにかくデフォルト以外のコンストラクターを定義する必要があります。

4

4 に答える 4

9

デフォルト以外のコンストラクターがそれらの1つと見なされないのはなぜですか?クラスで管理されているリソースがある場合、プログラマーはとにかくデフォルト以外のコンストラクターを定義する必要があります。

それは必ずしも真実ではありません。コンストラクターはリソースを取得しない可能性があります。他の関数もそれらを取得する可能性があります実際、リソースを取得する可能性のある多くの関数(コンストラクター自体を含む)が存在する可能性があります。たとえば、の場合は、リソースを取得します。したがって、リソースを取得する可能性のある他の関数と同じようにコンストラクターを考えてください。std::vector<T>resize()reserve()

このルールの考え方は、コピーを作成するときに、コンパイラによって生成されたデフォルトのコピーコードが機能しないということです。したがって、コピーセマンティックを自分で作成する必要があります。また、クラスはリソースを管理するため(どの関数がリソースを取得するかは関係ありません、完全に構築されたオブジェクトに対して、デストラクタが実行されることが保証されているため、デストラクタはリソースを解放する必要があります。したがって、デストラクタも定義する必要があります。また、C ++ 11では、移動セマンティクスも実装する必要があります。move-semanticの論理引数は、move semanticsでソースも変更したことを除いて、copy-semanticsの引数と同じです。Move-semanticは、臓器提供者によく似ています。あなたが他の人にあなたの臓器を与えるとき、あなたはもうそれを所有していません。

于 2011-10-06T09:06:05.737 に答える
2

それは三つのルールが何であるかではありません。

リソースを管理するクラスにはそのデストラクタが含まれるため、とにかく3つのルールが適用されます。重要なのは、デフォルト以外のコンストラクターは絶対に必要ではありませんが、他のコンストラクター(コピーコンストラクター/代入演算子)は必要です。

少なくとも、標準的なコンテナの要素などには不可欠でした。

現在、移動セマンティクス(c ++ 11)により、状況は少し変化し始めています。5のルールはありますか?「ベストプラクティス」と「経験則」の観点から、それがどのように機能するかはわかりません。

実際、すでに3つのルールのバリエーションを述べることができます。デストラクタを定義するクラスは、コピー/ムーブコンストラクタとコピー/ムーブ代入演算子も定義する必要があります。また、コピーコンストラクターが定義されている場合は、コピー代入演算子も定義する必要があります。また、移動コンストラクターが定義されている場合は、移動代入演算子も定義する必要があります。

とにかく、これはしばらくの間私の親指のルールになるでしょう。

于 2011-10-06T09:05:55.667 に答える
0

リソースを取得する場合(たとえば、新しいものを使用する場合)はまったく正しいですが、デストラクタでリソースを解放することを忘れないでください。デストラクタを作成したら、3つのルールが適用され、3つすべてを定義する必要があります。

ただし、たとえば、コピーセマンティクスで初期化するメンバー変数がクラスにいくつかある場合は、デストラクタは不要であり、ルールは適用されません。

于 2011-10-06T09:08:34.763 に答える
0

デフォルト以外のコンストラクターを定義することは、デストラクタなどが必要であることを自動的に意味するわけではありません。PODタイプを入力するための便宜として、そのコンストラクターを使用しているだけかもしれません。

そうは言っても、同じことがデフォルトのコンストラクターにも当てはまります。

基本的に、「ビッグスリーが必要ですか?」クラスがリソースを管理するときにトリガーされます。それでもデフォルトのコンストラクターは必要ないかもしれませんが、有効な初期状態を設定するにはコンストラクターが必要です。

その新しく構築された状態は、リソースのインスタンスをまだ所有していない可能性がありますが、所有していない場合は、所有していないことを認識している必要があります(たとえば、nullポインターがあります)。

ただし、多くの場合、ビッグ3も暗黙的に使用されます。たとえば、一時的なものはデフォルトで作成されます。デフォルト以外のコンストラクターが必要になる理由の1つは、暗黙のデフォルトコンストラクターが提供および使用されないようにするためです。

したがって、3つすべてを一度に定義する理由の1つは、コード(コンパイラーによって暗黙的に提供されるコードを含む)が正常なままであることを確認するためです。

ほとんどの場合、リソースを管理している場合はデフォルトのコンストラクターがあるため、ルールにそのことが記載されていますが、ある種のコンストラクターを定義している限り、問題はありません。

于 2011-10-06T09:11:14.080 に答える