たくさんのデータメンバーがいる長いクラスがあります。そのためのコピーコンストラクターを書きたいです。ただし、独自のコピーコンストラクターを作成すると、デフォルトのコピーコンストラクターにアクセスできなくなります。
自分のコピーコンストラクターでいくつかのポインターを修復したいだけです。そのため、デフォルトのコピーコンストラクターで実行できるオブジェクトの浅いコピーが必要です。
自分のコピーコンストラクターがある場合、デフォルトのコピーコンストラクターにアクセスする可能性はありますか?
たくさんのデータメンバーがいる長いクラスがあります。そのためのコピーコンストラクターを書きたいです。ただし、独自のコピーコンストラクターを作成すると、デフォルトのコピーコンストラクターにアクセスできなくなります。
自分のコピーコンストラクターでいくつかのポインターを修復したいだけです。そのため、デフォルトのコピーコンストラクターで実行できるオブジェクトの浅いコピーが必要です。
自分のコピーコンストラクターがある場合、デフォルトのコピーコンストラクターにアクセスする可能性はありますか?
変更したくないものを構造体にラップし、それから(個人的に)派生します。コピーコンストラクターで、基本クラスのコピーコンストラクターを呼び出すだけです。
いいえ、デフォルトと独自のコピーc-torの両方を持つことはできません。
ただし、この問題には2つの回避策があります。
1定義されたコピーセマンティクスを使用してポインタをクラスに囲みます
例:
class A {
public:
private:
int trivial1;
int trivial2;
...
SomePointer nontrivialMember;
};
class SomePointer {
public:
SomePointer(const SomePointer&); // here the non trivial part of A copy semantics
int* nonTrivialMember;
};
2些細なパラメータをいくつかの些細な構造で囲みます
例:
class A {
public:
A(const A& o) : data(o.data) {
// non trivial part
}
private:
struct Data {
int trivial1;
int trivial2;
...
} data;
int* nontrivialMember;
};
私は常に最初の解決策を選択します。
[アップデート]
私の2番目と非常によく似た3番目の解決策もあり、あなたの些細な部分を私的に継承された基本クラスで囲みます。私はまだ最初の解決策を好みます。
これに対する最も簡単なアプローチは、コピーコンストラクターで手動で「修復」を実行するクラスにポインターをラップすることです。そうすれば、デフォルトのコピーコンストラクターをうまく使用できます。
いいえ、ユーザー定義のコピーコンストラクターからデフォルトのコピーコンストラクターを呼び出す方法はありません。
デフォルトまたは独自のいずれかを使用できますが、両方を使用することはできません。オブジェクトごとに異なる機能を選択したい場合は、その場合を処理するメンバー関数を作成するだけです。
void DeepCopy(MyClass* rhs);
例えば。
独自に作成した場合、デフォルトのコピーコンストラクタにアクセスすることはできません。コンパイラはそれを生成しません。ただし、回避策があります。クラスをデータ構造とロジックに分割します。
例を参照してください:
struct Data
{
int i;
std::string s;
Data(): i(), s() {}
};
class Code: private Data
{
public:
Code() {}
Code(const Code& rhs): Data(rhs) // Call default copy ctor
{
i = 42; // Your copy part
return *this;
}
};
私の解決策は、以下に示す例のように、暗黙の(コンパイラーによって生成された)コピーコンストラクターへの不可能な呼び出しではなく、単純なmemcpy()です。
Class Foo
{
public:
...
Foo (Foo & other) {
// copies trivial part (and non-trivial part with possible wrong values)
memcpy(this, &other, sizeof(Foo));
// your non-trivial part here, overwrites the wrong values (if any) above.
}
}
ただし、副作用として、memcpy()は、これらの重要な部分もコピーします。これは無駄です。重要な部分にあまり多くのスペースが含まれていない場合、私は自分の解決策を好みます。
たとえば、以下のようなクラスは、ポインタのサイズが4バイトであると仮定すると、1つのポインタの4バイトのコピーのみを浪費します。
Class Bar
{
int x, y, z;
// memcpy() wastes these 4 bytes copy,
// since actual copy constructor wants a new string
string *s;
}
これは私にとってはうまくいきました...(C ++ 11、古い標準で機能するかどうかはわかりません)なぜそれが無限ループにならないのかわかりません。
class Foo {
public:
Foo(const Foo &orig) {
*this = orig;
... exchange pointers, do own stuff
}