コピー コンストラクターとコピー代入演算子 (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-name 型const
の単一の引数を取ると宣言されたコピー コンストラクターがある場合です。 このような場合、コンパイラが生成したコピー コンストラクターの引数も const
です。
コピー コンストラクターへの引数の型が const
ではない場合、const
オブジェクトのコピーによる初期化はエラーを生成します。 逆は当てはまりません。つまり、引数が const
の場合、const
ではないオブジェクトをコピーして初期化できます。
コンパイラが生成した代入演算子は const
では同じパターンに従います。 これらの演算子は、すべての基底クラスおよびメンバー クラスの代入演算子が const ClassName&
型の引数を受け取らない場合は、ClassName&
型の単一の引数を受け取ります。 この場合、クラスの生成された代入演算子は const
引数を受け取ります。
Note
コピー コンストラクターによって初期化されるか、コンパイラによって生成されるか、またはユーザーによって定義される場合、仮想基底クラスは構築される時点で 1 回だけ初期化されます。
影響はコピー コンストラクターの影響と似ています。 引数の型が const
ではない場合、const
オブジェクトからの代入ではエラーが発生します。 逆は当てはまりません。つまり、const
値が const
ではない値に代入された場合、代入は成功します。
オーバーロード代入演算子の詳細については、「代入」をご覧ください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示