web-dev-qa-db-ja.com

ディープコピーと浅いコピー

可能性のある複製:
ディープコピーとシャローコピーの違いは何ですか?

ディープコピーとシャローコピーの違いは何ですか。コピーコンストラクターはどのようなコピーを行いますか?

51
Ankur

浅いコピー:

コピーの一部のメンバーは、元のオブジェクトと同じオブジェクトを参照する場合があります。

class X
{
private:
    int i;
    int *pi;
public:
    X()
        : pi(new int)
    { }
    X(const X& copy)   // <-- copy ctor
        : i(copy.i), pi(copy.pi)
    { }
};

ここで、元のオブジェクトとコピーされたpiオブジェクトのXメンバーは、両方とも同じintを指します。


ディープコピー:

オリジナルのすべてのメンバーが複製されます(必要に応じて再帰的に)。共有オブジェクトはありません:

class X
{
private:
    int i;
    int *pi;
public:
    X()
        : pi(new int)
    { }
    X(const X& copy)   // <-- copy ctor
        : i(copy.i), pi(new int(*copy.pi))  // <-- note this line in particular!
    { }
};

ここでは、元のオブジェクトとコピーされたpiオブジェクトのXメンバーは異なるintオブジェクトを指しますが、これらは両方とも同じ値を持ちます。


デフォルトのコピーコンストラクター(自分で作成しない場合は自動的に提供されます)は、浅いコピーのみを作成します。

訂正:以下のいくつかのコメントは、デフォルトのコピーコンストラクタalwaysが浅いコピーを実行すると言うのは間違っていると正しく指摘しています。 (またはそのことについては、ディープコピー)。型のコピーコンストラクターが浅いコピーを作成するか、ディープコピーを作成するかまたは2つの中間の何かは、各メンバーのコピー動作の組み合わせに依存します。結局のところ、メンバーの型のコピーコンストラクターは、必要なことを何でも行うようにできます。

1998 C++標準のセクション12.8、パラグラフ8が上記のコード例について述べていることは次のとおりです。

クラスXの暗黙的に定義されたコピーコンストラクターは、サブオブジェクトのメンバーごとのコピーを実行します。 [...]各サブオブジェクトは、そのタイプに適した方法でコピーされます。[...] [I]サブオブジェクトがスカラー型の場合、組み込みの代入演算子が使用されます。

52
stakx

この典型的な例は、構造体またはオブジェクト(可変)へのポインターの配列です。

shallow copyは配列をコピーし、元のオブジェクトへの参照を維持します。

deep copyは、オブジェクトもコピー(クローン)するため、元のオブジェクトとは関係ありません。これに暗示されているのは、オブジェクト自体が深くコピーされることです。何かが深くコピーされたかどうかを知る本当の方法がないので、これは難しくなります。

コピーコンストラクターは、同じクラスの以前に作成されたオブジェクトで新しいオブジェクトを初期化するために使用されます。デフォルトでは、コンパイラは浅いコピーを作成しました。動的メモリ割り当てが関与しない場合、両方のオブジェクトがヒープ内の同じメモリ位置を指すため、浅いコピーは動的メモリ割り当てが関与しない場合は正常に機能します。したがって、この問題を解決するために、両方のオブジェクトが独自の属性のコピーを持つようにディープコピーを記述しました記憶に。

完全な例と説明で詳細を読むには、記事 Constructors and destructors を参照してください。

デフォルトのコピーコンストラクタは浅いです。必要に応じて、独自のコピーコンストラクターを深くまたは浅くすることができます。 C++ Notes:OOP:Copy Constructors を参照してください。

12
cletus

ディープコピーは、文字通りディープコピーを実行します。つまり、クラスに参照であるフィールドがある場合、それらの値は参照自体ではなくコピーされます。たとえば、参照タイプのフィールドを持つクラスAとBの2つのインスタンスがあり、ディープコピーを実行する場合、Aのそのフィールドの値を変更してもBの値には影響しません。浅いコピーでは、参照のみがコピーされるため、状況は異なります。したがって、コピーされたオブジェクトのこのフィールドを変更すると、元のオブジェクトに影響します。

コピーコンストラクターはどのようなコピーを行いますか?

実装に依存します。これは厳密なルールがないことを意味し、ディープコピーまたはシャローコピーのように実装できますが、コピーコンストラクターでディープコピーを実装するのが一般的な慣行であるということを知っています。ただし、デフォルトのコピーコンストラクターはシャローコピーを実行します。

3
n535