デフォルト以外のコピー コンストラクターと代入演算子 (ポインターのリストを含む) を必要とするクラスがあります。コピー コンストラクターと代入演算子の間のコードの重複を減らす一般的な方法はありますか?
4 に答える
すべての場合に機能するカスタム コピー コンストラクターと代入演算子を記述するための "一般的な方法" はありません。しかし、「copy-&-swap」というイディオムがあります。
class myclass
{
...
public:
myclass(myclass const&);
void swap(myclass & with);
myclass& operator=(myclass copy) {
this->swap(copy);
return *this;
}
...
};
多くの (すべてではない) 状況で役立ちます。もっとうまくやれることもある。ベクトルまたは文字列は、十分に大きい場合に割り当てられたストレージを再利用する、より適切な割り当てを持つことができます。
共通コードをプライベート メンバー関数に分解します。単純な (やや不自然な) 例:
#include <iostream>
class Test
{
public:
Test(const char* n)
{
name = new char[20];
strcpy(name, n);
}
~Test()
{
delete[] name;
}
// Copy constructor
Test(const Test& t)
{
std::cout << "In copy constructor.\n";
MakeDeepCopy(t);
}
// Assignment operator
const Test& operator=(const Test& t)
{
std::cout << "In assignment operator.\n";
MakeDeepCopy(t);
}
const char* get_name() const { return name; }
private:
// Common function where the actual copying happens.
void MakeDeepCopy(const Test& t)
{
strcpy(name, t.name);
}
private:
char* name;
};
int
main()
{
Test t("vijay");
Test t2(t); // Calls copy constructor.
Test t3("");
t3 = t2; // Calls the assignment operator.
std::cout << t.get_name() << ", " << t2.get_name() << ", " << t3.get_name() << '\n';
return 0;
}
My &My::operator = (My temp) // thanks, sellibitze
{
swap (*this, temp);
return *this;
}
特殊な を実装しstd::swap<> (My &, My &)
ます。
かなりの数の投稿者によってすでに指摘されているように、operator= でコピー コンストラクターを使用して新しいオブジェクトを作成し、次に swap を使用することは、operator= でコードを複製する必要がないために使用される一般的な手法です。
そうは言っても、この手法が適切かどうかを判断するのに役立つように、この手法の長所と短所をいくつか指摘したいと思います.
プロ - 例外的な安全性
オブジェクトにスローを引き起こす可能性のあるリソース要件があり、スワップがスローされないと仮定すると、この手法は例外安全性の強力な保証を提供します (割り当てられているオブジェクトが他のオブジェクトの値を取得しているか、変更されていません)。
Con - リソースフットプリント
この手法の問題点は、古いオブジェクトを解放する前に完全な新しいオブジェクトを作成する必要があることです。オブジェクトが多くのリソースを必要とする場合、これは問題になる可能性があります。