次の方法で共有


コピー コンストラクターとコピー代入演算子 (C++)

Note

C++ 11 以降では、2 種類の代入 (コピーの代入移動の代入) が言語でサポートされています。 この記事では、特に明示的に記載しない限り、"代入" はコピーの代入を意味します。 移動の代入については、「移動コンストラクターと移動代入演算子 (C++)」をご覧ください。

代入演算と初期化操作では、いずれもオブジェクトがコピーされます。

  • 代入: あるオブジェクトの値が別のオブジェクトに代入されると、最初のオブジェクトが 2 番目のオブジェクトにコピーされます。 このコードでは、b の値を a にコピーします。

    Point a, b;
    ...
    a = b;
    
  • 初期化: 初期化は、新しいオブジェクトを宣言するとき、関数の引数を値で渡すとき、または関数から値で返すときに発生します。

クラス型のオブジェクトに「コピー」の意味を定義できます。 たとえば、次のコードを検討してみましょう。

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

前のコードは、「FILE1.DAT から FILE2.DAT に内容をコピーする」を意味する場合もありますが、「FILE2.DAT を無視して b を FILE1.DAT への 2 番目のハンドルにする」という意味もあります。各クラスには、次のように適切なコピーのセマンティクスを割り当てる必要があります。

  • クラス型への参照を返し、const 参照で渡される 1 つのパラメーターを取る代入演算子 operator= を使用します (ClassName& operator=(const ClassName& x); など)。

  • コピー コンストラクターを使用します。

コピー コンストラクターを宣言していない場合、コンパイラはメンバーごとのコピー コンストラクターを生成します。 同様に、コピー代入演算子を宣言していない場合、コンパイラはメンバーごとのコピー代入演算子を生成します。 コピー コンストラクターを宣言しても、コンパイラで生成されるコピー代入演算子は抑制されません。また、その逆も同様です。 いずれか 1 つを実装する場合、もう 1 つも実装することをお勧めします。 両方を実装すると、コードの意味が明確になります。

コピー コンストラクターは、ClassName& 型の引数を受け取ります。ここで、ClassName はクラス名を指します。 次に例を示します。

// spec1_copying_class_objects.cpp
class Window
{
public:
    Window( const Window& );            // Declare copy constructor.
    Window& operator=(const Window& x); // Declare copy assignment.
    // ...
};

int main()
{
}

Note

可能な限り、コピー コンストラクターの const ClassName& 引数の型を作成します。 これによって、コピー コンストラクターが誤ってコピーしたオブジェクトを変更しないようにすることができます。 また、const オブジェクトからコピーすることもできます。

コンパイラによって生成されたコピー コンストラクター

ユーザー定義のコピー コンストラクターのように、コンパイラによって生成されるコピー コンストラクターには、"class-name への参照" 型の 1 つの引数があります。例外は、すべての基底クラスとメンバー クラスに、class-nameconstの単一の引数を取ると宣言されたコピー コンストラクターがある場合です。 このような場合、コンパイラが生成したコピー コンストラクターの引数も const です。

コピー コンストラクターへの引数の型が const ではない場合、const オブジェクトのコピーによる初期化はエラーを生成します。 逆は当てはまりません。つまり、引数が const の場合、const ではないオブジェクトをコピーして初期化できます。

コンパイラが生成した代入演算子は const では同じパターンに従います。 これらの演算子は、すべての基底クラスおよびメンバー クラスの代入演算子が const ClassName& 型の引数を受け取らない場合は、ClassName& 型の単一の引数を受け取ります。 この場合、クラスの生成された代入演算子は const 引数を受け取ります。

Note

コピー コンストラクターによって初期化されるか、コンパイラによって生成されるか、またはユーザーによって定義される場合、仮想基底クラスは構築される時点で 1 回だけ初期化されます。

影響はコピー コンストラクターの影響と似ています。 引数の型が const ではない場合、const オブジェクトからの代入ではエラーが発生します。 逆は当てはまりません。つまり、const 値が const ではない値に代入された場合、代入は成功します。

オーバーロード代入演算子の詳細については、「代入」をご覧ください。