본문 바로가기
스터디/C++

[ C++ ] 깊은 복사( deep copy )와 얕은 복사 ( shallow copy )

by 알 수 없는 사용자 2019. 9. 26.

얕은 복사( shallow copy )는 디폴트 복사 생성자에 의한 멤버 대 멤버의 복사 방식을 말한다.

하지만 이는 멤버 변수가 힙의 메모리 공간을 참조하는 경우에 문제가 된다. 

 

예를 보자.

 

A형 객체 a와 b가 있고, a는 객체 생성 시 초기화를 했다.

반면 b는 a의 디폴트 복사생성자에 의해 멤버 대 멤버 복사가 일어났다. 즉, 얕은 복사가 일어났다.

 

근데 예상된 결과와는 다르게 소멸자 호출이 한번 일어났다.

 

이유는 char형 포인터인 name 때문이다.

멤버 대 멤버 복사이기 때문에 객체 a의 name을 가리키는 주소 값을 b도 같이 할당받아,

두 객체가 같은 문자열을 참조하는 문제가 생긴다.

 

그래서 만약 객체 a가 먼저 소멸된다고 가정하면,

a의 소멸자 호출이 일어나면 name을 delete 해준다.

하지만 b의 소멸자 호출이 일어나면 이미 소멸된 문자열을 대상으로 delete 연산을 하기에 문제가 발생해버린다.

 

그렇지만 멤버변수가 힙의 메모리 공간을 참조하지 않는다면 문제는 따르지 않는다.

( 멤버변수 name을 지운 것뿐이다. )

 

이처럼 얕은 복사는 간단하지만 멤버변수에 따른 문제점이 발생하는 것을 고려해야 한다.

 

이런 문제를 해결하기 위해 나온 것이 깊은 복사( deep copy )다.

얕은 복사는 디폴트 복사 생성자인 반면, 깊은 복사는 복사 생성자를 재정의함으로써 원하는 멤버 변수만 복사를 해주는 형식이다. 그래서 얕은 복사의 문제점을 해결할 수 있다.

 

( 글쓴이의 생각으로는 얕은 복사는 디폴트 복사 생성자로 대충 복사하는 감이라면, 깊은 복사는 복사 생성자를 재정의해줌으로써 객체간의 같은 메모리 공간 참조를 막아주기에 깊은 복사라고 하는 것 같다.)

 

그럼 아까의 예제를 가져와서 복사 생성자를 재정의해보겠다.

 

문제가 해결됐다! 

 

* 복사 생성자에 const로 인자를 받아오는데, 그 이유는 기존의 객체의 멤버 변수 값을 건드리지 않겠다는 의미이다.

  그래서 복사 생성자에 const로 받아오는 것을 권장한다.