コピー コンストラクターのパラメーターを参照渡しする必要があるのはなぜですか?
9 に答える
参照によるものでなければ、値によるものだからです。そのためには、コピーを作成し、そのためにコピー コンストラクターを呼び出します。しかし、それを行うには、新しい値を作成する必要があるため、コピー コンストラクターなどを呼び出します...
(「コピーを作成するには、コピーを作成する必要がある」ため、無限再帰が発生します。)
値渡しはコピーコンストラクターを呼び出すため:)
参照渡しの代わりに値渡しがあります。値渡しは実際にはコピー渡しです。コピーを作成するには、コピー コンストラクターが必要です。
コピー コンストラクターを呼び出すためだけにコピーを作成する必要があるとしたら、それは難しい問題です。
(コンパイラで無限再帰が発生し、実際にそのようなプログラムを取得することはないと思います。)
合理的な理由に加えて、§12.8/3 の標準で禁止されています。
クラス X のコンストラクターの宣言は、その最初のパラメーターが X 型 (オプションで cv 修飾) であり、他のパラメーターがないか、他のすべてのパラメーターにデフォルト引数がある場合、形式が正しくありません。
値で渡した場合、無限に再帰的になります
組み込みデータ型(ここではcar)以外の引数を取る関数(例:int f(car c))を呼び出すときはいつでも、呼び出し元から提供された実際のオブジェクトを、呼び出された関数のパラメーターの変数にコピーする必要があります。
例:
car carobj;
f(carobj);
つまり、にコピーcarobj
しc
ます。
carobj
c
関数のパラメータにコピーする必要がありますf
。
コピーを実現するために、コピーコンストラクターが呼び出されます。
この場合、f
値渡しを使用して呼び出された関数、つまり関数f
は値渡しを行うように宣言されます。
関数f
が参照によって渡される場合、その宣言は次のようになります。
int f(car &c);
この場合、
car carobj;
f(carobj);
コピーコンストラクタは必要ありません。
この場合、c
はのエイリアスになりcarobj
ます。
上記の2つのシナリオを使用して、わかりやすくするために、次のように要約します。
関数がオブジェクトの値としてパラメーターを受け取るように宣言されている場合、オブジェクトのコピーコンストラクターが呼び出されます。
関数がパラメーターを「参照渡し」として受け取るように宣言されている場合、パラメーターは呼び出し元によって提供されたオブジェクトのエイリアスになります。コピーコンストラクタは必要ありません!
ここで問題となるのは、なぜ参照渡しが必要なのかということです。コピーコンストラクターが参照を受け入れる場合、受信変数は提供されたオブジェクトのエイリアスになります。したがって、呼び出し元が指定したオブジェクトの値をコピーして、引数リストのコンストラクターの変数をコピーするために、コンストラクターのコピー(この場合はそれ自体を呼び出す)は必要ありません。
それ以外の場合、コピーコンストラクターが呼び出し元から提供されたオブジェクトを値として受け取る場合、つまり値を渡す場合は、指定されたオブジェクトのコピーコンストラクターが必要です。したがって、提供されたオブジェクトを呼び出し元から関数自体(この場合はコピーコンストラクター)に取り込むには、コピーコンストラクターを呼び出す必要があります。これは、関数宣言中に同じ関数を呼び出すことに他なりません。
これが、コピーコンストラクターへの参照を渡す理由です。
オブジェクトを値ではなく参照として渡す必要があります。これは、オブジェクトを値で渡すと、コピー コンストラクターを使用してそのコピーが構築されるためです。つまり、コピー コンストラクターはコピーを作成するために自分自身を呼び出します。メモリの。
オブジェクトを参照として渡すことは非常に重要です。オブジェクトがコピー コンストラクターに値として渡された場合、そのコピー コンストラクターはそれ自体を呼び出して、実パラメーターを仮パラメーターにコピーします。したがって、コピー コンストラクターへの無限の呼び出しチェーンが開始されます。このプロセスは、システムのメモリが不足するまで続きます。
したがって、コピー コンストラクターでは、パラメーターを常に参照として渡す必要があります。
参照渡しでない場合は、値渡しになります。引数が値渡しの場合、そのコピー コンストラクターは自分自身を呼び出して、実パラメーターを仮パラメーターにコピーします。このプロセスは、システムのメモリが不足するまで続きます。したがって、コピーコンストラクターが呼び出されないように、参照渡しする必要があります。