깊은 사본과 얕은 사본의 차이점은 무엇입니까?


754

깊은 사본과 얕은 사본의 차이점은 무엇입니까?


6
어떤 기술이 적용됩니까?
Suresh Varma

42
@SureshVarma, 그것은 프로그래밍 개념입니다!
Manish Shrivastava

답변:


759

얕은 사본은 가능한 한 적게 복제합니다. 컬렉션의 얕은 복사본은 요소가 아니라 컬렉션 구조의 복사본입니다. 얕은 사본을 사용하면 이제 두 컬렉션이 개별 요소를 공유합니다.

딥 카피는 모든 것을 복제합니다. 컬렉션의 딥 카피는 원본 컬렉션의 모든 요소가 복제 된 두 컬렉션입니다.


.NET MemberwiseClone () 구현은 일반적인 의미에서 얕은 복사 이상의 기능을 수행합니다.
Lu55

5
게으른 사본 뿐만 아니라 혼합 사본 도 있으며 그중 일부만 복제합니다 ( 여기 인스턴스가 있음 ). ;)
cregox

X의 얕은 사본은 X의 요소를 바꿀 수 있지만 깊은 사본은 할 수 없습니까?
punstress 7:24에

1
수집 구조 란 무엇입니까?
Honey

1
@Honey Collections는 여러 데이터 항목을 저장하는 다양한 데이터 구조 일 수 있습니다. 파이썬에서는 튜플,리스트, 사전 등이 있습니다
Murphy

850

폭 대 깊이; 객체를 루트 노드로 사용하는 참조 트리의 관점에서 생각하십시오.

얕은:

복사하기 전에 얕은 복사 얕은 완료

변수 A와 B는 서로 다른 메모리 영역을 나타내며, B가 A에 할당되면 두 변수는 동일한 메모리 영역을 나타냅니다. 나중에 내용 중 하나를 수정하면 내용을 공유 할 때 다른 내용에 즉시 반영됩니다.

깊은:

복사하기 전에 딥 카피 딥 완료

변수 A 및 B는 B가 A에 할당 될 때 A가 가리키는 메모리 영역의 값이 B가 가리키는 메모리 영역에 복사되는 메모리 영역의 값을 나타냅니다. 나중에 내용의 수정은 A 또는 B에 고유하게 유지됩니다. 내용은 공유되지 않습니다.


32
다음은 위키 피 디아 문서에서는이 그림은 당신을 위해 문맥 이해가되지 않는 경우에서 오는입니다 en.wikipedia.org/wiki/Object_copy#Shallow_copy
코빈

4
얕은 복사의 경우 배열 B를 변경하면 A & B가 동일한 메모리 위치를 가리 키기 때문에 배열 A에 반영됩니다.
tek3

3
단일 행에서 참조 별 사본 대 값별 사본. 답이 맞는지 확실하지 않습니다!
Mannu

2
이미지는 직접 인용하지 않고 위키 피 디아에서 가져온
jasonleonhard

9
@jasonleonhard 그래서 9 년 전 이미지 삽입은 지원되지 않았기 때문에 이미지에 URL을 넣었습니다. 따라서 URL은 그 출처를 인용했습니다. 커뮤니티는 나중에 어떤 종류의 인용을 편집하지 않고 URL을 포함 된 이미지로 만들었습니다. 4 살짜리 최고 의견은 또한 당신이 지적한 것을 지적합니다. 보세요 : stackoverflow.com/posts/184780/revisions 왜 답을 스스로 인용으로 편집하지 않습니까? 다음에 누군가 내 10 살짜리 글쓰기 스타일에 대해 불만을 제기 할 수 없을 수도 있습니다.
dlamblin

156

요컨대, 그것은 무엇을 가리키는 지에 달려 있습니다. 얕은 사본에서 객체 B는 메모리에서 객체 A의 위치를 ​​가리 킵니다. 딥 카피에서는 객체 A의 메모리 위치에있는 모든 것이 객체 B의 메모리 위치에 복사됩니다.

이 위키 기사에는 훌륭한 다이어그램이 있습니다.

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


113

다음 이미지를 고려하십시오

여기에 이미지 설명을 입력하십시오

예를 들어 Object.MemberwiseClone는 생성 얕은의 복사 링크를

ICloneable 인터페이스를 사용 하면 여기에 설명 된대로 카피를 얻을 수 있습니다


28
그림은 천 단어의 가치가 있습니다.
Levi Fuller

6
오 소년, 의미를 찾기 위해 여기에 왔습니다. 이것이 도움이 된 유일한 대답입니다.
Karan Singh

1
이것은 가장 단순하지만 필요한 것을 보여줍니다.
hina10531 년

1
최고의 삽화
Muhammad Nayab

69

특히 iOS 개발자의 경우 :

경우 BA는 얕은 복사A그것처럼 원시 데이터를 다음 B = [A assign];과 같이의 개체에 대한 B = [A retain];

B와 A는 동일한 메모리 위치를 가리 킵니다.

경우 BA는 딥 카피 의가 A, 다음은 같다B = [A copy];

B와 A는 다른 메모리 위치를 가리킴

B 메모리 주소는 A와 동일

B는 A와 같은 내용을 가지고 있습니다


8
"B 메모리 주소는 A와 같습니다"-어떻게됩니까?

2
Deep Copy에서 "B 메모리 주소는 A와 동일하지 않습니다"
ismail baig

60

얕은 복사 : 한 개체에서 다른 개체로 멤버 값을 복사합니다.

Deep Copy : 한 개체의 멤버 값을 다른 개체로 복사합니다.
                     모든 포인터 객체가 복제되고 딥 복사됩니다.

예:

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

{C ++와 관련하여 동일한 유형 _t의 A와 B라는 두 개의 객체를 상상해보십시오.

얕은 사본 : 단순히 A에 대한 참조 사본을 B로 복사합니다. A의 주소 사본으로 생각하십시오. 따라서 A와 B의 주소는 동일합니다. 즉, 동일한 메모리 위치, 즉 데이터 내용을 가리 킵니다.

딥 카피 : A의 모든 멤버를 간단히 복사하고 B의 다른 위치에 메모리를 할당 한 다음 복사 된 멤버를 B에 할당하여 딥 카피를 달성합니다. 이런 식으로 A가 존재하지 않으면 B는 여전히 메모리에서 유효합니다. 올바른 용어는 클로닝인데, 둘 다 완전히 동일하지만 아직 다릅니다 (즉, 메모리 공간에 두 개의 다른 엔티티로 저장 됨). 포함 / 제외 목록을 통해 딥 카피 중에 선택할 속성을 결정할 수있는 복제 래퍼를 제공 할 수도 있습니다. 이것은 API를 만들 때 매우 일반적인 관행입니다.

관련된 스테이크를 이해하면 얕은 사본을 ONLY_IF로 선택할 수 있습니다 . C ++ 또는 C에서 처리 할 포인터가 너무 많으면 객체의 얕은 복사본을 수행하는 것이 실제로 나쁜 생각입니다.

EXAMPLE_OF_DEEP COPY_ 예를 들어, 이미지 처리 및 객체 인식을 시도 할 때 처리 영역에서 "무의미하고 반복적 인 모션"을 마스킹해야합니다. 이미지 포인터를 사용하는 경우 해당 마스크 이미지를 저장하도록 지정해야합니다. 지금 ... 이미지의 얕은 복사본을 수행하는 경우 포인터 참조가 스택에서 종료되면 참조와 해당 복사본이 손실됩니다. 즉, 어느 시점에서 액세스 위반의 런타임 오류가 발생합니다. 이 경우 필요한 것은 CLONING하여 이미지의 깊은 사본입니다. 이런 식으로 나중에 필요할 때 마스크를 검색 할 수 있습니다.

EXAMPLE_OF_SHALLOW_COPY StackOverflow 사용자와 비교할 때 지식이 충분 하지 않으므로이 부분을 삭제하고 명확하게 설명 할 수있는 좋은 예를 제시하십시오. 그러나 실제로 프로그램이 무한정 실행되는 것을 알고 있다면 함수 호출을 사용하여 스택에서 "푸시 팝"연속 작동하는 것을 알면 얕은 복사를하는 것이 좋지 않습니다. 아마추어 또는 초보자에게 무언가를 시연하는 경우 (예 : C / C ++ 튜토리얼). 그러나 감시 및 탐지 시스템 또는 Sonar Tracking System과 같은 응용 프로그램을 실행하는 경우 프로그램을 조만간 종료시킬 수 있으므로 대상을 얕게 복사하지 않아야합니다.


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. 당신의 단순 복사본을 수행 할 때 MainObject1, MainObject2생성됩니다 field2의 복사 된 값을 포함 field1가리키는 여전히 및 ContainObject1자체. 이후 있습니다 field1원시적 형태의, 그 값이 복사됩니다 field2하지만 이후는 ContainedObject1, 목적은 MainObject2여전히 가리 킵니다 ContainObject1. 에 대한 변경 그래서 ContainObject1MainObject1반영됩니다 MainObject2.

이제 이것이 얕은 사본이라면, 깊은 사본을 보자?

딥 카피 란 무엇입니까?

깊은 복사는 모든 필드를 복사하고 필드가 가리키는 동적으로 할당 된 메모리의 복사본을 만듭니다. 깊은 복사는 개체가 참조하는 개체와 함께 개체를 복사 할 때 발생합니다. 딥 카피

이 그림에서 MainObject1는 필드가 field1int 형, 그리고 ContainObject1유형을 ContainObject. 당신의 깊은 사본을 수행 할 때 MainObject1, MainObject2생성됩니다 field2의 복사 된 값을 포함 field1하고 ContainObject2의 복사 된 값을 포함 ContainObject1. 에 대한 변경 주 ContainObject1MainObject1의 반영하지 것이다 MainObject2.

좋은 기사


이 예제 field3가 그 문제만큼 깊은 것을 시도하고 이해할 수있는 위치에있는 경우 를 언급하지만 그것은 당신의 잘못이 아닙니다.이 예제의 # 3은 어디에서 발생 ContainObject2 합니까?
Robb_2015

16

객체 지향 프로그래밍에서 형식에는 멤버 필드 모음이 포함됩니다. 이러한 필드는 값 또는 참조 (즉, 값에 대한 포인터)로 저장 될 수 있습니다.

단순 사본에서는 유형의 새 인스턴스가 작성되고 값이 새 인스턴스로 복사됩니다. 참조 포인터도 값과 같이 복사됩니다. 따라서 참조는 원본 객체를 가리 킵니다. 참조로 저장된 멤버에 대한 변경 사항은 참조 된 오브젝트의 사본이 없으므로 원본과 사본 모두에 나타납니다.

딥 카피에서는 값으로 저장된 필드가 이전과 같이 복사되지만 참조로 저장된 객체에 대한 포인터는 복사되지 않습니다. 대신, 참조 된 객체로 딥 카피가 만들어지고 새 객체에 대한 포인터가 저장됩니다. 참조 된 객체를 변경해도 다른 객체 사본에는 영향을 미치지 않습니다.


12

'ShallowCopy'는 'Source'와 동일한 메모리 위치를 가리 킵니다. 'DeepCopy'는 메모리의 다른 위치를 가리 키지 만 내용은 동일합니다.


이것은 약간 잘못된 것입니다. 얕은 사본과 깊은 사본은 객체를 메모리의 새로운 위치에 복사하고, 깊은 사본은 자식 객체를 복사하는 반면, 얕은 사본은 새 객체가 오래된 자식을 참조하도록합니다. 원래 객체를 참조하지 않고 읽기가 어렵습니다.
Bill K

10

얕은 복제 :
정의 : "개체의 얕은 사본은 '주된'물체를 복사하지만 내부 개체는 복사하지 않습니다." 사용자 정의 객체 (예 : Employee)에 기본, 문자열 유형 변수 만 있으면 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

이것은 포인터를 사용하여 문자열을 나타내는 언어에서만 작동합니다. DHA가 시도하는 요점은 얕게 복사하면 포인터가 동일한 (단일) 원본 콘텐츠에 대한 포인터 만 복제하고 딥 카피는 포인터의 참조 된 콘텐츠도 복제한다는 것입니다. 두 방법 모두 표면 내용을 복사합니다. 언어가 문자열을 표면 리터럴 컨텐츠로 저장하는 경우 (예 : WAV 헤더 내부)이 예제는 작동하지 않습니다. 난해하지 않은 대부분의 실제 문제에 대해서는 아마도 너무 까다로울 수 있습니다.
DragonLord

8

딥 카피

깊은 복사는 모든 필드를 복사하고 필드가 가리키는 동적으로 할당 된 메모리의 복사본을 만듭니다. 깊은 복사는 개체가 참조하는 개체와 함께 개체를 복사 할 때 발생합니다.

얕은 사본

얕은 사본은 객체의 비트 단위 사본입니다. 원본 객체의 값과 정확히 일치하는 새 객체가 생성됩니다. 객체의 필드 중 하나가 다른 객체에 대한 참조 인 경우 참조 주소 만 복사됩니다. 즉, 메모리 주소 만 복사됩니다.


그 링크는 더 이상 작동하지 않습니다. 이제 2019 년 2 월부터 웹 디자인에 관한 기사를 썼습니다 (저자가 저자가 아닌 경우에 한하지 않습니까?).
PhilPhil

7

얕은 복사 -원본 및 얕은 복사 된 개체 내의 참조 변수에는 공통 개체에 대한 참조가 있습니다.

딥 카피 -원본 및 딥 복사 된 객체 내부의 참조 변수에 다른 객체에 대한 참조가 있습니다 .

clone은 항상 얕은 복사를 수행합니다.

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은

거짓 사실

거짓 거짓 거짓

오리지널 오브젝트를 변경하면 깊은 오브젝트가 아닌 얕은 오브젝트에 반영됩니다.

  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

간단한 용어로, 얕은 사본은 참조 기준으로 호출하고 깊은 사본은 기준으로 호출과 유사합니다.

Call By Reference에서 함수의 공식 및 실제 매개 변수는 모두 동일한 메모리 위치와 값을 나타냅니다.

Call By Value에서 함수의 형식 매개 변수와 실제 매개 변수는 서로 다른 메모리 위치를 나타내지 만 값은 같습니다.


5

arr1과 arr2라는 두 개의 배열이 있다고 상상해보십시오.

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

5

얕은 사본은 새 복합 객체를 구성하고 참조를 원본 객체에 삽입합니다.

얕은 복사와 달리 심도 복사는 새 복합 객체를 구성하고 원본 복합 객체의 원본 객체의 사본도 삽입합니다.

예를 들어 봅시다.

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). 파이썬이 여기서하는 일은 새로운 복합 객체를 만들지 만 내부의 객체는 orignal 객체를 가리키고 있습니다.

여기에 이미지 설명을 입력하십시오

이미지에서 외부 목록에 대한 새 사본을 작성했습니다. 그러나 내부 목록은 원래 목록과 동일하게 유지됩니다.

이제 우리는를 사용하여 심층 복사를 만듭니다 z = copy.deepcopy(x). 파이썬이 여기서하는 일은 내부 목록뿐만 아니라 외부 목록에 대한 새 객체를 만듭니다. 아래 이미지에 표시된대로 (빨간색 강조 표시됨).

여기에 이미지 설명을 입력하십시오

끝 코드 False에서 y와 z는 동일한 객체가 아니기 때문에 prints .

HTH.


2

얕은 복사는 새 개체를 만든 다음 현재 개체의 고정되지 않은 필드를 새 개체로 복사합니다. 필드가 값 유형 인 경우 필드의 비트 별 복사가 수행됩니다. A에 대한 기준 입력 -> 참조 복사되지만 언급 객체 아니다; 따라서 원본 객체와 복제본은 동일한 객체를 참조합니다.

정밀 복사는 새 객체를 만든 다음 현재 객체의 비 정적 필드를 새 객체로 복사합니다. 필드가 값 유형 인 경우 필드의 비트 별 복사가 수행됩니다. 필드가 참조 유형 인 경우 참조 된 오브젝트의 새 사본이 수행됩니다. 복제 할 클래스는 [Serializable]로 플래그되어야합니다.


2

[블로그]에서 가져온 것 : http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

딥 카피 에는 한 객체의 내용을 사용하여 동일한 클래스의 다른 인스턴스를 만듭니다. 딥 카피에서 두 객체에는 동일한 정보가 포함될 수 있지만 대상 객체에는 자체 버퍼와 리소스가 있습니다. 두 개체의 파괴는 나머지 개체에 영향을 미치지 않습니다. 오버로드 된 할당 연산자는 객체의 깊은 복사본을 만듭니다.

얕은 복사 는 한 객체의 내용을 같은 클래스의 다른 인스턴스에 복사하여 미러 이미지를 만드는 것을 포함합니다. 참조와 포인터를 직접 복사하기 때문에 두 객체는 ​​예측할 수없는 다른 객체와 동일한 외부에 포함 된 내용을 공유합니다.

설명:

복사 생성자를 사용하여 멤버별로 데이터 값을 복사합니다. 이 복사 방법을 얕은 복사라고합니다. 객체가 내장 클래스로 구성되고 포인터가없는 간단한 클래스 인 경우 이는 허용됩니다. 이 함수는 값과 객체를 사용하며 그 동작은 얕은 복사로 변경되지 않으며 멤버 인 포인터의 주소 만 복사되며 주소가 가리키는 값은 아닙니다. 그러면 객체의 데이터 값이 함수에 의해 실수로 변경됩니다. 함수가 범위를 벗어나면 모든 데이터가 포함 된 객체의 복사본이 스택에서 튀어 나옵니다.

객체에 포인터가 있으면 깊은 복사를 실행해야합니다. 개체의 깊은 복사본을 사용하면 메모리가 여유 저장소의 개체에 할당되고 지정된 요소가 복사됩니다. 딥 카피는 함수에서 반환 된 객체에 사용됩니다.


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

일기 복사 :

Array는 클래스이므로 참조 유형이므로 array1 = array2는 동일한 배열을 참조하는 두 개의 변수가됩니다.

그러나이 예를보십시오 :

  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]);
    }

얕은 복제 는 복제 된 배열이 나타내는 메모리 만 복사됨을 의미합니다.

배열에 값 유형 객체가 포함 된 경우 값이 복사됩니다 .

배열에 참조 유형이 포함 된 경우 참조 만 복사되므로 결과적으로 구성원이 동일한 객체를 참조하는 두 개의 배열이 있습니다 .

참조 유형이 중복되는 깊은 사본을 만들려면 배열을 반복하고 각 요소를 수동으로 복제해야합니다.


다른 언어는 모르지만 C # / VB에서는 값 형식 배열을 얕게 복사해도 값이 복사 되지 않습니다 . 두 배열은 동일한 객체를 나타냅니다. 양식에 버튼을 추가하고이 코드를 추가하여 다음을 확인하십시오.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

당신은 맞습니다. 클론에서 복제를 사용하여 내 대답을보다 정확하게 수정했습니다. "값 유형의 배열을 복사하면 값이 복사되지 않습니다"라는 것이 옳습니다. 그러나 배열에서 복제를 사용하면됩니다. 나는 그것을 설명하려고 노력했다. 감사합니다
lukaszk

1

나는 다음과 같은 내용을 이해하게되었습니다.

얕은 복사는 객체 값 유형 (int, float, bool) 필드를 대상 객체에 복사하고 객체의 참조 유형 (문자열, 클래스 등)은 대상 객체의 참조 로 복사됩니다 . 이 대상 참조 유형은 소스 객체의 메모리 위치를 가리 킵니다.

딥 카피는 객체의 값과 참조 유형을 대상 객체의 완전히 새로운 카피로 복사합니다. 이는 값 유형과 참조 유형 모두에 새 메모리 위치가 할당됨을 의미합니다.


0

위의 모든 정의에 가장 일반적으로 사용되는 하나 이상의 딥 카피는 클래스의 카피 생성자 (또는 오버로드 할당 연산자)에 있습니다.

얕은 복사->는 복사 생성자를 제공하지 않을 때입니다. 여기서는 개체 만 복사되지만 클래스의 모든 구성원은 복사되지 않습니다.

Deep copy->는 클래스에서 복사 생성자 또는 과부하 할당을 구현하기로 결정하고 클래스의 모든 멤버를 복사 할 수있게하는 시점입니다.

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.