つのルール の状態として、クラスのクラスコピーコンストラクターを定義する必要があることを理解しています。また、次のコードが示すように、コピーコンストラクターの引数は通常const
であることに気付きます。
class ABC {
public:
int a;
int b;
ABC(const ABC &other)
{
a = other.a;
b = other.b;
}
}
私の質問は、コピーコンストラクターの引数がconstでない場合にどうなるかです。
class ABC
{
public:
int a;
int b;
ABC(ABC &other)
{
a = other.a;
b = other.b;
}
}
コピーコンストラクタの引数がconstの場合、2番目の実装が失敗する場合があることを理解しています。また、コピーコンストラクターの引数がconstの場合、コピーされるオブジェクトは処理中にその内容を変更しません。ただし、一部の人々はまだ最初の実装ではなく2番目の実装を使用していることに気づきます。 2番目の実装が推奨される理由はありますか?
論理的には、コピーを作成したいだけのオブジェクトを変更しても意味がありませんが、このオブジェクトがコピーされた回数を保存したい場合など、場合によっては意味があることもあります。しかし、これはこの情報を格納するmutable
メンバー変数で機能し、constオブジェクトでも変更できます(2番目の点はこのアプローチを正当化します)
Constオブジェクトのコピーを作成できるようにしたい。しかし、引数をconst修飾子で渡さない場合、constオブジェクトのコピーを作成できません...
一時オブジェクトは右辺値であり、非constへの参照にバインドできないため、一時参照からコピーを作成できませんでした。より詳細な説明については、私はお勧めします 問題に関するハーブサッターの記事
クラスのコンシューマーが最後に期待するのは、コピーされたオブジェクトを変更するコピーコンストラクターです。したがって、常にconstとしてマークする必要があります。
ここでconstが必要になる理由は2つあります。
2番目のケースを例示するには:
_ class ABC
{
public:
int a;
int b;
ABC(const ABC &other)
{
a = other.a;
b = other.b;
}
ABC operator+(const ABC &other)
{
ABC res;
res.a = a + other.a;
res.b = b + other.b;
return res;
}
}
...
ABC A;
a.a = 1;
a.b = 2;
ABC B(a+a);
_
_a+a
_はABC型の一時オブジェクトであるため、コンストラクタがABC(ABC &other)
の場合、これはコンパイルされません。しかし、それがABC(const ABC &other)
の場合、計算の一時的な結果を使用して、それを参照として渡すことができます。
他のいくつかの回答が指摘しているように、その引数を変更したコピーコンストラクターは不愉快な驚きです。しかし、それだけが問題ではありません。コピーコンストラクターは、temporariesの引数と共に使用されることがあります。 (例:関数からの戻り。)そして、説明されているように、一時への非const参照は飛ぶことはありません elsewhere SO。
コピーコンストラクターがパラメーターをconstとして指定しない場合、このフラグメントはコンパイルされません。
const ABC foo;
ABC bar(foo);
コピーコンストラクターは、コピー元のオブジェクトを変更しないでください。そのため、const
パラメーターではother
が優先されます。どちらも機能しますが、渡されたオブジェクトが関数によって変更されるべきではないことが明確に示されているため、const
が推奨されます。
const
はユーザー専用です。実際の実行可能ファイルには存在しません。
技術的な意味での「必須」ではありません。 非推奨になりました ですが、標準にはそのような獣さえいます。推論のリンクをたどってください。
私たちが期待するコピーのセマンティクスは、「テンプレート」を変更せず、すべての点でまったく同じであるクローンを提供することです。これにより、元のフォームを特定することが困難になります。
予想されていることですが、他の方法で行うコピークターがあると2度考えます。これはユーザーを驚かせ、バグを引き起こす可能性があります。そして欲求不満とノイズ、カウントを確認するために「auto_ptrのベクター」をググってみてください。
残りの質問は、「実装でオリジナルに触れないことを誓いますが、別の署名が必要です」です。では、どのような署名ですか? TとT&を試してみましょう。
Tは、コピーActorを使用可能にする必要があるため、ドロップアウトし、それを実装しています。再帰:recursionを参照してください。
それはT&を残す。これは実際には多くのケースで機能します。しかし、元のオブジェクトがたまたまconst形式で座っているか、一時的なものである場合は、失敗します。なぜ雨がまったく降らないという賢明なケースを妨げるのですか?
コピーコンストラクターがソースインスタンスを変更してはならないという基本的な前提に加えて、この記事では、constを使用する実際の技術的な理由について詳しく説明します。
http://www.geeksforgeeks.org/copy-constructor-argument-const/
つまり、それと私は引用します:
"...コンパイラが作成した一時オブジェクトは非const参照にバインドできません..."