3

最近、Rule of Three を読みましたが、これに違反しているのでしょうか?

私の GUI アプリケーションではMainFrameInterfaceCircuitBreadboardなどのクラス (クラス名は指標です) には、それぞれのインスタンスが 1 つあります。それらのコンストラクターで、いくつかのリソース (メモリ) を割り当て、それらをデストラクタで安全に解放します。

したがって、デストラクタのみを定義しましたが、コピー コンストラクタ代入演算子は定義しませんでした。

私はそれらを必要としないと確信していますが、規則に違反しているかどうか、また規則に従うために何ができる/すべきか知りたいです?

4

5 に答える 5

6

3 のルールとは、すべてのビッグ 3 に対処することですが、必要がない場合は、必ずしもそれらを定義する必要があるという意味ではありません。それらを提供するか、禁止します。あなたがしてはいけないことは、それらを無視することです。


したがって、デストラクタのみを定義しましたが、コピー コンストラクタとコピー オペレータは定義しませんでした。
3 のルールに違反していますか?

はい、ルール違反です。コンパイラはコピー コンストラクターとコピー代入演算子を生成します。コンストラクターでメモリを割り当て、デストラクタで解放するため、これらのコピーは間違ったセマンティクスを持つことになります。それらはポインターをコピーし、同じメモリをエイリアスする 2 つのクラスを持つことになります。 . 割り当ては古いメモリを解放することさえせず、単にポインタを上書きします。

これは問題ですか?

あなたが暗示しているように、コピーを作成したり、それらのクラスのインスタンスに割り当てたりしなければ、何も問題はありません。ただし、安全のために、コピー コンストラクターとコピー代入演算子を private として宣言する (そしてわざわざ定義しない) ことをお勧めします。

= deleteC++11 では、代わりに次の構文を使用できます。

T(T const&) = delete; // no copy constructor
T& operator=(T const&) = delete; // no copy assignment
于 2012-02-04T07:13:01.940 に答える
2

これは、アプリケーションロジックと、ユーザーにインターフェイスクラスをどのように文書化したかに大きく依存します。

通常、優れたc ++プログラマーは、3つのルール(「コピーとスワップのイディオム」を知っている場合は半分)と、c ++ 11(セマンティクスの移動)の場合は5と1/2のルールを知っている必要があります。

クラスがリソースを管理し、同じクラスがコピー可能である場合(つまり、copy ctorとassigment演算子がprivateとして定義されていない場合)、独自のcopyctorと代入演算子を記述してディープコピーを行うことが非常に重要です。

ただし、クラスをREFERENCEとして渡すことで常にクラスをいじっている場合は、デフォルトのコピーコンストラクターと代入演算子をプライベートとして定義することをお勧めします。これにより、valyを渡したり、誤ってコピーしたりした場合でも、コンパイラーが警告を表示します。

于 2012-02-04T07:20:06.690 に答える
2

プライベート コピー コンストラクターと代入演算子を宣言する (実装しない) 必要があります。関数を実装しないようにしてください。これにより、コピーされるべきではないクラスのあらゆる種類のコピーが防止されます。

于 2012-02-04T07:13:06.060 に答える
1

あなたがそれを必要としないならば、それに従ってはいけません。三つのルールの背後にある動機は、デストラクタが必要な場合、それは通常、動的な割り当て解除を行う必要があるためです。

割り当て解除も行う場合は、コピーコンストラクターと代入演算子も必要になります。何かへのポインタを持つクラスがあると想像してください。

struct Foo
{
    Foo() { ptr_ = new int; }
    ~Foo() { delete ptr_; }
    int* ptr_;
};

コピーコンストラクタと代入演算子を定義しないため、のコピーを作成するときは常に、元のコピーとコピーの両方が同じ;Fooへのポインタを使用します。intオリジナルまたはコピーのいずれかが破棄されると、ポインタが解放され、もう一方には使用できないデータが残ります。

Foo(cont Foo& other) {
    other.ptr_ = new int(*ptr_);
}

// Same for operator=

コンストラクタ/デストラクタで動的割り当てを行わない場合は、実際にはコピーコンストラクタや代入演算子は必要ない可能性があります(必ずしもそうとは限りません)。

于 2012-02-04T07:20:20.947 に答える
1

はい、その定義による 3 つのルールに違反しています。

ただし、これは「経験則」です。一般的なガイドライン。コピー構築や代入操作が必要ない場合は、実装しないでください。他の人は、それらをプライベートとして宣言し、それらを空として定義することを提案しています. 私はさらに一歩進んで、それらを定義することさえしないと言います。

それらを定義すると、空のメソッドを呼び出す可能性があります。代わりに、それらを未定義のままにしておきます。これらのメソッドを呼び出そうとすると、メソッド定義が見つからないため、リンカー エラーが発生します。実行時エラーや望ましくない動作よりもビルド時エラーを優先します。

于 2012-02-04T07:17:47.257 に答える