ディープコピーとシャローコピーの違いは何ですか?


754

ディープコピーとシャローコピーの違いは何ですか?


6
それはどのテクノロジーに該当しますか?
Suresh Varma、2011年

42
@SureshVarma、それはプログラミングの概念です!
Manish Shrivastava 2015

回答:


761

浅いコピーはできるだけ複製しません。コレクションの浅いコピーは、要素ではなくコレクション構造のコピーです。浅いコピーでは、2つのコレクションが個々の要素を共有します。

ディープコピーはすべてを複製します。コレクションのディープコピーは、元のコレクションのすべての要素が複製された2つのコレクションです。


.NETのMemberwiseClone()実装は、従来の意味での浅いコピー以上のことを行う
Lu55

5
混合コピーもあることに注意してください(遅延コピーなどだけでなく)、その一部だけを複製しますここにインスタンスがあります)。;)
cregox、2015年

Xの浅いコピーはXの要素を変更できますが、深いコピーは変更できませんか?
パンスト

1
コレクション構造とは何ですか?
ハニー

1
@Honeyコレクションは、複数のデータ項目を格納する多様なデータ構造にすることができます。Pythonにはタプル、リスト、辞書などがあります
マーフィー

852

幅と深さ。オブジェクトをルートノードとする参照ツリーについて考えます。

浅い:

コピー前 浅いコピー 浅い完了

変数AとBは異なるメモリ領域を参照し、BがAに割り当てられている場合、2つの変数は同じメモリ領域を参照します。どちらか一方のコンテンツに対する後の変更は、コンテンツを共有しているため、すぐに他方のコンテンツに反映されます。

深い:

コピー前 深いコピー 深い完了

変数AとBはメモリの異なる領域を参照します。BがAに割り当てられると、Aが指すメモリ領域の値がBが指すメモリ領域にコピーされます。いずれかの内容に対する後の変更は、AまたはBに固有のままです。内容は共有されません。


33
これは、この図があなたにとってコンテキスト外では意味をなさない場合に使用されるウィキペディアの記事ですen.wikipedia.org/wiki/Object_copy#Shallow_copy
corbin

4
浅いコピーの場合、配列Bに変更を加えると、AとBの両方が同じメモリ位置を指すため、配列Aに反映されますか?
tek3

3
単一行で、参照によるコピーと値によるコピー。答えが正しいかどうかわからない!
Mannu

2
引用なしでウィキペディアから直接撮った画像
jasonleonhard

10
@jasonleonhardつまり、9年前は、画像の埋め込みがサポートされていなかったため、画像にURLを付けました。したがって、URLはそのソースを引用しています。コミュニティは後に、URLを何らかの引用を編集することなく、埋め込み画像にしました。4歳のトップコメントもあなたの指摘を指摘しています。見てください:stackoverflow.com/posts/184780/revisions引用を自分で回答に編集してみませんか?次に誰かが私の10歳の書体について何らかの不満を持っているとき、私は利用できないかもしれません。
dlamblin 2017

156

要するに、何が何を指しているかによります。浅いコピーでは、オブジェクトBはメモリ内のオブジェクトAの場所を指します。ディープコピーでは、オブジェクトAのメモリロケーションにあるすべてのものがオブジェクトBのメモリロケーションにコピーされます。

このウィキの記事には素晴らしい図があります。

http://en.wikipedia.org/wiki/Object_copy


114

次の画像を検討してみてください

ここに画像の説明を入力してください

たとえば、Object.MemberwiseClone浅いコピーリンクを作成します

ICloneableインターフェイスを使用すると、ここで説明するようにディープコピーを取得できます


28
写真は千の言葉の価値があります。
Levi Fuller 2016年

6
ああ、その意味を知るためにここに来た。これが助けになった唯一の答えです。
Karan Singh

1
これは最も単純ですが、必要なものだけを示しています。
hina10531 2018年

1
最高のイラスト
ムハンマドナヤブ

69

特にiOS開発者向け:

場合B浅いコピーA場合、プリミティブデータのためにそれはようなものだB = [A assign];、それはようなものだオブジェクトとするためにB = [A retain]

BとAが同じメモリ位置を指している

場合BであるディープコピーのはA、それは次のようですB = [A copy];

BとAが異なるメモリ位置を指している

BメモリアドレスはAと同じ

BはAと同じ内容です


8
「BメモリアドレスはAと同じ」-どうしてですか?

2
ディープコピーでは、「BのメモリアドレスはAのメモリアドレスとは
異なります

60

浅いコピー:あるオブジェクトから別のオブジェクトにメンバー値をコピーします。

ディープコピー:あるオブジェクトから別のオブジェクトにメンバー値をコピーします。
                     ポインターオブジェクトは複製され、ディープコピーされます。

例:

class String
{
     int   size;
     char* data;
};

String  s1("Ace");   // s1.size = 3 s1.data=0x0000F000

String  s2 = shallowCopy(s1);
 // s2.size =3 s2.data = 0X0000F000
String  s3 = deepCopy(s1);
 // s3.size =3 s3.data = 0x0000F00F
 //                      (With Ace copied to this location.)

47

ここでは、短くてわかりやすい答えを見たことがありません。試してみましょう。

浅いコピーでは、ソースによってポイントされたオブジェクトはすべて宛先によってもポイントされます(そのため、参照されるオブジェクトはコピーされません)。

ディープコピーでは、コピー元が指すオブジェクトがコピーされ、コピー先がコピー先を指します(これにより、参照される各オブジェクトが2つになります)。これは、オブジェクトツリーを再帰します。



36

{2つのオブジェクトを想像してください:(C ++に関して)同じタイプの_tのAとBであり、AからBへの浅い/深いコピーについて考えている}

浅いコピー: Aへの参照をBにコピーするだけです。それをAのアドレスのコピーと考えてください。したがって、AとBのアドレスは同じになります。つまり、同じメモリ位置、つまりデータの内容を指します。

ディープコピー: Aのすべてのメンバーのコピーを作成し、Bの別の場所にメモリを割り当ててから、コピーしたメンバーをBに割り当てて、ディープコピーを実現します。このようにして、Aが存在しなくなっても、Bはメモリ内で引き続き有効です。使用する正しい用語は、両方とも完全に同じであるが、異なる(つまり、2つの異なるエンティティとしてメモリスペースに格納される)ことを知っているクローンです。クローンラッパーを提供して、包含/除外リストを介して、ディープコピー中に選択するプロパティを決定することもできます。これは、APIを作成するときの一般的な方法です。

あなたはシャローコピーを行うことを選択することができますONLY_IFあなたが利害関係を理解しています。C ++またはCで扱うポインタが非常に多い場合、オブジェクトの浅いコピーを行うのは本当に悪い考えです。

EXAMPLE_OF_DEEP COPY_例として、画像処理とオブジェクト認識を実行しようとしているときに、「関連のない反復的な動き」を処理領域からマスクする必要があります。画像ポインタを使用している場合、それらのマスク画像を保存する仕様があるかもしれません。NOW ...画像の浅いコピーを行う場合、ポインタ参照がスタックから削除されると、参照とそのコピーが失われます。つまり、ある時点でアクセス違反のランタイムエラーが発生します。この場合、必要なのは、イメージを複製することによるイメージのディープコピーです。この方法で、将来必要になる場合に備えてマスクを取得できます。

EXAMPLE_OF_SHALLOW_COPY私はStackOverflowのユーザーに比べてあまり詳しくないので、この部分を削除して、明確にできれば良い例を示してください。しかし、プログラムが無限に実行されることがわかっている場合、つまり、関数呼び出しを伴うスタックでの連続的な「プッシュポップ」操作を知っている場合は、浅いコピーを行うのは良い考えではないと思います。アマチュアまたは初心者に何かをデモンストレーションしている場合(C / C ++のチュートリアルなど)、それはおそらく問題ありません。しかし、監視および検出システムやソナー追跡システムなどのアプリケーションを実行している場合は、オブジェクトを浅くコピーし続けることは、遅かれ早かれプログラムを強制終了するためです。


32
char * Source = "Hello, world.";

char * ShallowCopy = Source;    

char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);        

「ShallowCopy」は「Source」と同じメモリ内の場所を指します。'DeepCopy'はメモリ内の別の場所を指していますが、内容は同じです。


22

浅いコピーとは何ですか?

浅いコピーは、オブジェクトのビット単位のコピーです。元のオブジェクトの値の正確なコピーを持つ新しいオブジェクトが作成されます。オブジェクトのフィールドのいずれかが他のオブジェクトへの参照である場合、参照アドレスのみがコピーされます。つまり、メモリアドレスのみがコピーされます。浅いコピー

この図では、MainObject1フィールドがあるfield1int型の、およびContainObject1タイプのをContainObject。の浅いコピーを実行するとMainObject1MainObject2field2、のコピーされた値を含み、それ自体をfield1指し示すように作成されContainObject1ます。以来ことに留意されたいfield1プリミティブ型であり、その値はにコピーされfield2なくためContainedObject1の目的であるが、MainObject2まだを指しますContainObject1。したがって、ContainObject1inに加えられた変更はすべてMainObject1に反映されMainObject2ます。

これが浅いコピーである場合、深いコピーとは何かを見てみましょう。

ディープコピーとは

ディープコピーはすべてのフィールドをコピーし、フィールドによってポイントされる動的に割り当てられたメモリのコピーを作成します。ディープコピーは、オブジェクトが参照するオブジェクトとともにオブジェクトがコピーされるときに発生します。 ディープコピー

この図では、MainObject1はフィールド持つfield1int型のを、およびContainObject1タイプのContainObject。あなたはの深いコピーを行うとMainObject1MainObject2使用して作成されたfield2のコピーされた値を含むfield1ContainObject2のコピーされた値を含みますContainObject1ContainObject1inに加えられた変更はにMainObject1は反映されないことに注意してくださいMainObject2

良い記事


これはあなたの責任ではありませんが、この例はfield3、その問題と同じくらい深く何かを試して理解する立場にあるときに言及していますが、その例の#3はどこで発生していContainObject2 ますか?
Robb_2015

16

オブジェクト指向プログラミングでは、型にはメンバーフィールドのコレクションが含まれます。これらのフィールドは、値または参照(つまり、値へのポインタ)によって格納されます。

浅いコピーでは、タイプの新しいインスタンスが作成され、値が新しいインスタンスにコピーされます。参照ポインタも値と同じようにコピーされます。したがって、参照は元のオブジェクトを指しています。参照によって保存されたメンバーへの変更は、参照されたオブジェクトのコピーが作成されなかったため、オリジナルとコピーの両方に表示されます。

ディープコピーでは、値によって格納されるフィールドは以前と同様にコピーされますが、参照によって格納されるオブジェクトへのポインターはコピーされません。代わりに、参照オブジェクトのディープコピーが作成され、新しいオブジェクトへのポインターが格納されます。これらの参照オブジェクトに加えられた変更は、オブジェクトの他のコピーには影響しません。


12

「ShallowCopy」は「Source」と同じメモリ内の場所を指します。'DeepCopy'はメモリ内の別の場所を指していますが、内容は同じです。


これは少し誤解を招く可能性があります。浅いコピーと深いコピーの両方でオブジェクトがメモリ内の新しい場所にコピーされ、深いコピーでも子オブジェクトがコピーされますが、浅いコピーでは新しいオブジェクトが古い子を参照するだけです。元のオブジェクトを参照せずに読むことは困難です。
ビルK

10

浅いクローニング:
定義:「オブジェクトの浅いコピーは「メイン」オブジェクトをコピーしますが、内部オブジェクトはコピーしません。」カスタムオブジェクト(たとえば、従業員)がプリミティブなString型の変数のみを持っている場合は、Shallow Cloningを使用します。

Employee e = new Employee(2, "john cena");
Employee e2=e.clone();

super.clone();オーバーライドされたclone()メソッドに戻り、ジョブが終了します。

ディープクローニング
定義:「浅いコピーとは異なり、ディープコピーはオブジェクトの完全に独立したコピーです。」
Employeeオブジェクトが別のカスタムオブジェクトを保持することを意味します。

Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");

次に、オーバーライドされたclone()メソッドで 'Address'オブジェクトのクローンを作成するコードを記述する必要があります。そうでない場合、Addressオブジェクトは複製されず、複製されたEmployeeオブジェクトのAddressの値を変更するとバグが発生し、元の値も反映されます。


8
var source = { firstName="Jane", lastname="Jones" };
var shallow = ShallowCopyOf(source);
var deep = DeepCopyOf(source);
source.lastName = "Smith";
WriteLine(source.lastName); // prints Smith
WriteLine(shallow.lastName); // prints Smith
WriteLine(deep.lastName); // prints Jones

それは良い例ではありません。浅いコピーは、ほとんどの場合、データをコピーせずにオブジェクトをすばやくコピーするために使用されますが、オブジェクトが共有データを変更する必要があると、その深いコピーが取得されます。あなたの例はおそらく初心者を混乱させるでしょう。
CMircea 2010

これは、ポインタを使用して文字列を表す言語でのみ機能します。DHAが作成しようとしている点は、浅いコピーは同一の(単一の)元のコンテンツへのポインターを複製するだけであり、ディープコピーはポインターの参照されたコンテンツも複製するということです。どちらの方法でも、サーフェスコンテンツがコピーされます。言語が文字列を表面リテラルコンテンツとして保存している場合(WAVヘッダー内など)、この例は機能しません。これはおそらく、難解ではない実際の問題のほとんどにとってはうるさすぎます。
DragonLord 2014年

8

ディープコピー

ディープコピーはすべてのフィールドをコピーし、フィールドによってポイントされる動的に割り当てられたメモリのコピーを作成します。ディープコピーは、オブジェクトが参照するオブジェクトとともにオブジェクトがコピーされるときに発生します。

浅いコピー

浅いコピーは、オブジェクトのビット単位のコピーです。元のオブジェクトの値の正確なコピーを持つ新しいオブジェクトが作成されます。オブジェクトのフィールドのいずれかが他のオブジェクトへの参照である場合、参照アドレスのみがコピーされます。つまり、メモリアドレスのみがコピーされます。


そのリンクは悲しいことに機能しなくなりました-それは今ウェブデザインに関する2019年2月の記事を指しています(著者が千里眼でない限り)。
PhilPhil

7

浅いコピー -元のオブジェクトと浅いコピーのオブジェクト内の参照変数は、共通オブジェクトを参照しています。

ディープコピー -元のオブジェクトとディープコピーされたオブジェクト内の参照変数は、異なるオブジェクトを参照してます。

クローンは常に浅いコピーを行います。

public class Language implements Cloneable{

    String name;
    public Language(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

メインクラスは次のとおりです-

public static void main(String args[]) throws ClassNotFoundException, CloneNotSupportedException{

      ArrayList<Language> list=new ArrayList<Language>();
      list.add(new Language("C"));
      list.add(new Language("JAVA"));

      ArrayList<Language> shallow=(ArrayList<Language>) list.clone();
      //We used here clone since this always shallow copied.

      System.out.println(list==shallow);

      for(int i=0;i<list.size();i++)
      System.out.println(list.get(i)==shallow.get(i));//true

      ArrayList<Language> deep=new ArrayList<Language>();
      for(Language language:list){
          deep.add((Language) language.clone());
      }
      System.out.println(list==deep);
      for(int i=0;i<list.size();i++)
          System.out.println(list.get(i)==deep.get(i));//false

} 

上記のOutPutは、

false true true

false false false

元のオブジェクトで行われた変更は、深いオブジェクトではなく浅いオブジェクトに反映されます。

  list.get(0).name="ViSuaLBaSiC";
  System.out.println(shallow.get(0).getName()+"  "+deep.get(0).getName());

OutPut- ViSuaLBaSiC C


7

正式な定義ではなく例を挙げたいと思います。

var originalObject = { 
    a : 1, 
    b : 2, 
    c : 3,
};

このコードは、浅いコピーを示しています

var copyObject1 = originalObject;

console.log(copyObject1.a);         // it will print 1 
console.log(originalObject.a);       // it will also print 1 
copyObject1.a = 4; 
console.log(copyObject1.a);           //now it will print 4 
console.log(originalObject.a);       // now it will also print 4

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // now it will print 1

このコードはディープコピーを示しています

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // !! now it will print 1 !!

取得中1 1 4 4 4 4 4 4
Suresh Prajapati

ディープコピーでは、copyObject.a = 8を実行してからチェックします。適切な回答が得られることを願っています。
Vivek Mehta

5
struct sample
{
    char * ptr;
}
void shallowcpy(sample & dest, sample & src)
{
    dest.ptr=src.ptr;
}
void deepcpy(sample & dest, sample & src)
{
    dest.ptr=malloc(strlen(src.ptr)+1);
    memcpy(dest.ptr,src.ptr);
}

5

簡単に言うと、浅いコピーは参照による呼び出しに似ており、深いコピーは値による呼び出しに似ています。

参照による呼び出しでは、関数の正式なパラメーターと実際のパラメーターの両方が同じメモリの場所と値を参照します。

値による呼び出しでは、関数の正式なパラメーターと実際のパラメーターの両方が異なるメモリ位置を参照しますが、値は同じです。


5

arr1とarr2という2つの配列があるとします。

arr1 = arr2;   //shallow copy
arr1 = arr2.clone(); //deep copy

5

浅いコピーは、新しい複合オブジェクトを構築し、その参照を元のオブジェクトに挿入します。

浅いコピーとは異なり、deepcopyは新しい複合オブジェクトを構築し、元の複合オブジェクトの元のオブジェクトのコピーも挿入します。

例を見てみましょう。

import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)

上記のコードはFALSEを出力します。

方法を見てみましょう。

元の複合オブジェクトx=[1,[2]](オブジェクト内にオブジェクトがあるため、複合と呼ばれます(開始))

ここに画像の説明を入力してください

画像でわかるように、リスト内にリストがあります。

次に、を使用してその浅いコピーを作成しy = copy.copy(x)ます。ここでpythonが行うことは、新しい複合オブジェクトを作成しますが、それらの内部のオブジェクトは元のオブジェクトを指しています。

ここに画像の説明を入力してください

画像では、外側のリストの新しいコピーを作成しています。しかし、内部リストは元のリストと同じままです。

次に、を使用してそれのディープコピーを作成しz = copy.deepcopy(x)ます。ここでのpythonの機能は、外部リストと内部リストの新しいオブジェクトを作成することです。下の画像に示すように(赤で強調表示)。

ここに画像の説明を入力してください

最後に、prints Falseは、yとzが同じオブジェクトではないためです。

HTH。


2

浅いコピーとは、新しいオブジェクトを作成し、現在のオブジェクトの非静的フィールドを新しいオブジェクトにコピーすることです。フィールドが値タイプの場合->フィールドのビットごとのコピーが実行されます。以下のための基準タイプ - >参照がコピーされているが、参照されるオブジェクトはありません。したがって、元のオブジェクトとそのクローンは同じオブジェクトを参照します。

ディープコピーとは、新しいオブジェクトを作成し、現在のオブジェクトの非静的フィールドを新しいオブジェクトにコピーすることです。フィールドが値タイプの場合 ->フィールドのビットごとのコピーが実行されます。フィールドが参照タイプの場合 -> 参照されたオブジェクトの新しいコピーが実行されます。複製するクラスには、[Serializable]のフラグを付ける必要があります。


2

[ブログ]からの引用:http : //sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

ディープコピーでは、1つのオブジェクトのコンテンツを使用して、同じクラスの別のインスタンスを作成します。ディープコピーでは、2つのオブジェクトに同じ情報が含まれている場合がありますが、ターゲットオブジェクトには独自のバッファーとリソースがあります。どちらのオブジェクトを破棄しても、残りのオブジェクトには影響しません。多重定義された代入演算子は、オブジェクトの深いコピーを作成します。

浅いコピーでは、1つのオブジェクトの内容を同じクラスの別のインスタンスにコピーすることにより、ミラーイメージを作成します。参照とポインタを直接コピーするため、2つのオブジェクトは、他のオブジェクトと同じ外部に含まれるコンテンツを共有し、予測不能になります。

説明:

コピーコンストラクターを使用して、データ値をメンバーごとにコピーするだけです。このコピー方法は、浅いコピーと呼ばれます。オブジェクトが組み込み型で構成され、ポインターがない単純なクラスの場合、これは許容されます。この関数は値とオブジェクトを使用し、その動作は浅いコピーでは変更されません。メンバーであるポインターのアドレスのみがコピーされ、アドレスが指している値はコピーされません。その後、オブジェクトのデータ値が関数によって誤って変更されます。関数がスコープ外になると、すべてのデータを含むオブジェクトのコピーがスタックからポップされます。

オブジェクトにポインタがある場合、ディープコピーを実行する必要があります。オブジェクトのディープコピーでは、メモリが空きストアのオブジェクトに割り当てられ、ポイントされている要素がコピーされます。ディープコピーは、関数から返されるオブジェクトに使用されます。


2

他の回答にさらに追加するには、

  • オブジェクトの浅いコピーは、値型ベースのプロパティの値によるコピーを実行し、参照型ベースのプロパティの参照によるコピーを実行します。
  • オブジェクトのディープコピーは、値タイプベースのプロパティの値ごとのコピーを実行するだけでなく、(参照タイプの)階層の深い参照タイプベースのプロパティの値ごとのコピーも実行します。

2

浅いコピーは新しい参照を作成しませんが、深いコピーは新しい参照を作成します。

これは、深くて浅いコピーを説明するプログラムです。

public class DeepAndShollowCopy {
    int id;
    String name;
    List<String> testlist = new ArrayList<>();

    /*
    // To performing Shallow Copy 
    // Note: Here we are not creating any references. 
      public DeepAndShollowCopy(int id, String name, List<String>testlist)
       { 

       System.out.println("Shallow Copy for Object initialization");
       this.id = id; 
       this.name = name; 
       this.testlist = testlist; 

       }
    */  

    // To performing Deep Copy 
    // Note: Here we are creating one references( Al arraylist object ). 
    public DeepAndShollowCopy(int id, String name, List<String> testlist) {
        System.out.println("Deep Copy for Object initialization");
        this.id = id;
        this.name = name;
        String item;
        List<String> Al = new ArrayList<>();
        Iterator<String> itr = testlist.iterator();
        while (itr.hasNext()) {
            item = itr.next();
            Al.add(item);
        }
        this.testlist = Al;
    }


    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Oracle");
        list.add("C++");
        DeepAndShollowCopy copy=new DeepAndShollowCopy(10,"Testing", list);
        System.out.println(copy.toString());
    }
    @Override
    public String toString() {
        return "DeepAndShollowCopy [id=" + id + ", name=" + name + ", testlist=" + testlist + "]";
    }
}

1

アラリーのコピー:

配列はクラスです。つまり、それは参照型であるため、array1 = array2は同じ配列を参照する2つの変数になります。

しかし、この例を見てください:

  static void Main()
    {
        int[] arr1 = new int[] { 1, 2, 3, 4, 5 }; 
        int[] arr2 = new int[] { 6, 7, 8, 9, 0 };

        Console.WriteLine(arr1[2] + " " + arr2[2]);
        arr2 = arr1;
        Console.WriteLine(arr1[2] + " " + arr2[2]); 
        arr2 = (int[])arr1.Clone();
        arr1[2] = 12;
        Console.WriteLine(arr1[2] + " " + arr2[2]);
    }

浅いクローンは、クローンされた配列によって表されるメモリのみがコピーされることを意味します。

配列に値タイプのオブジェクトが含まれている場合、値がコピーされます。

配列に参照型が含まれている場合は、参照のみがコピーされますその結果、メンバーが同じオブジェクトを参照する2つの配列があります

ディープコピーを作成するには、参照タイプが重複している場合、配列をループして各要素を手動で複製する必要があります。


他の言語については知りませんが、C#/ VBでは、値型の配列を浅くコピーしても値コピーされませ。2つの配列は同じオブジェクトを参照します。フォームにボタンを追加して表示するには、このコードを追加しますprivate void button1_Click(object sender, EventArgs e) { int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{6,7,8,9,0}; MessageBox.Show(arr1[2] + " " + arr2[2]); arr2 = arr1; MessageBox.Show(arr1[2] + " " + arr2[2]); arr1[2] = 12; MessageBox.Show(arr1[2] + " " + arr2[2]); }
DeanOC

あなたは正しい、私は配列のクローンを使用して私の答えをより正確に修正しました 「値タイプの配列を浅くコピーしても値はコピーされない」というのは間違いなく正しいことですが、配列でcloneを使用することはできます。私はそれを説明しようとしました、それを試してください。ありがとう
lukaszk

1

以下のことから理解できるようになりました。

浅いコピーは、オブジェクト値の型(int、float、bool)フィールドをターゲットオブジェクトにコピーし、オブジェクトの参照型(文字列、クラスなど)は、ターゲットオブジェクトの参照としてコピーされます。このターゲットでは、参照タイプはソースオブジェクトのメモリロケーションを指しています。

ディープコピーは、オブジェクトの値と参照型をターゲットオブジェクトの完全に新しいコピーにコピーします。つまり、値タイプと参照タイプの両方に新しいメモリ位置が割り当てられます。


0

上記のすべての定義に加えて、最も一般的に使用されるもう1つのディープコピーは、クラスのコピーコンストラクター(またはオーバーロード代入演算子)にあります。

浅いコピー->は、コピーコンストラクターを提供しない場合です。ここでは、オブジェクトのみがコピーされ、クラスのすべてのメンバーはコピーされません。

ディープコピー->は、クラスにコピーコンストラクターまたはオーバーロードの割り当てを実装することを決定し、クラスのすべてのメンバーのコピーを許可する場合です。

MyClass& MyClass(const MyClass& obj) // copy constructor for MyClass
{
          // write your code, to copy all the members and return the new object
}
MyClass& operator=(const MyClass& obj) // overloading assignment operator,
{
          // write your code, to copy all the members and return the new object
}

0

コピーコンストラクターは、同じクラスの以前に作成されたオブジェクトで新しいオブジェクトを初期化するために使用されます。デフォルトでは、コンパイラは浅いコピーを書き込みました。動的メモリ割り当てが関係していない場合、浅いコピーは正常に機能します。動的メモリ割り当てが関係している場合、両方のオブジェクトがヒープ内の同じメモリ位置を指すため、この問題を取り除くために、両方のオブジェクトが独自の属性のコピーを持つように深いコピーを作成しましたメモリ内。詳細な例と説明を読むには、C ++コンストラクターの記事を参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.