4

私のプログラムは、次のRectように定義された単純な構造を使用しています

struct Rect {
    int x1, y1, x2, y2;

    Rect()
    : x1(0), y1(0), x2(0), y2(0) { }

    Rect(int x1, int y1, int x2, int y2)
    : x1(x1), y1(y1), x2(x2), y2(y2) { }
};

コピー/移動コンストラクターまたは代入演算子を定義する必要がありますか、またはそれらを自動生成するためにコンパイラーに頼ることができますか? 問題は、速度と使用上の理由のコンテキストにあります (たとえば、移動コンストラクターはプログラムの実行速度に影響を与える可能性があります)。

コンストラクターとオペレーターは非常に反復的な作業なので、コンパイラーに頼ってそれらを自動的に生成できると便利です。

    Rect(const Rect& r)
    : x1(r.x1), y1(r.y1), x2(r.x2), y2(r.y2) { }

    Rect(Rect&& r)
    : x1(r.x1), y1(r.y1), x2(r.x2), y2(r.y2) { }

    Rect& operator = (const Rect& r) {
        x1 = r.x1;
        y1 = r.y1;
        x2 = r.x2;
        y2 = r.y2;
    }
4

4 に答える 4

6

Q1: それらを自動生成するためにコンパイラに頼ることはできますか?

はい(あなたの例では)。C++11 標準 (第 12 節)、または記事Implicit Move Won't Go!を参照してください。(最後の近くの素敵な図)。要約すると (そして単純化するために)、次のすべての特別なメンバー関数が自動生成されます (暗黙的に宣言され、デフォルトとして定義されます)。

  • デストラクタ– 宣言しなかったためです。
  • コンストラクターのコピー– MC と MAO のいずれも宣言していないためです。
  • Copy Assignment Operator – MC と MAO のいずれも宣言しなかったためです。
  • コンストラクターを移動– D、CC、CAO、MAO のいずれも宣言していないため。
  • Move Assignment Operator – D、CC、CAO、MC のいずれも宣言していないため。

(リスト アイテムを 1 行ずつ保持するためだけに醜いイニシャルを使用しました。) 上記の「なぜなら」に加えて、デストラクタ以外のすべてに対して、生成されたデフォルトが意味を成さなければならないという追加の制約があります。つまり、すべてのデータ メンバはコピー可能 (CC と CAO の場合) または移動可能 (MC と MAO の場合)。(実際には、正確なルールはもう少し複雑ですが、ここで標準を言い換えたくはありません。)

Q2: 自動生成された関数は正しいですか?

はい(あなたの例では)。すべてのデータ メンバー (ここではプレーンints) は正しいコピー/移動セマンティクスを持っています (それらのコピー/移動コンストラクターと代入演算子は正しいことを行い、自動生成されたものRectはそれらを呼び出します)。

Q3: とにかく、それらを手動で定義する必要がありますか?

(あなたの例では)それには利点がなく、潜在的な問題もありません(あなたの例のように、コメントを参照してください)。

于 2013-08-31T13:00:28.287 に答える
1

データ メンバーは組み込み型であるため、コンパイラを中継することができます。そのため、オブジェクトのコピーがメンバーごとのコピーによって作成される可能性があります。これは、コピー/移動コンストラクターも代入演算子も定義しない場合に当てはまります。データ メンバーとしてポインターがあった場合は、それらが必要になることがあります。

于 2013-08-31T12:12:06.177 に答える
1

構造体 Rect のメンバーがすべて c++ ビルトイン型であるため、明示的なコピー コンストラクターに割り当てを記述する必要はありません。そのため、コンパイラーはビットごとのコピー コンストラクターを生成します。コードでは、コンパイラーに完全に依存できると思います。

于 2013-08-31T12:18:11.963 に答える