프로그래밍 언어 공부/C++

얕은 복사와 깊은 복사 / 복사 생성자 및 대입 연산자 행동 절차

설탕중독 2022. 6. 24. 21:58

 

얕은 복사와 깊은 복사

 

얕은 복사 (Shallow Copy)

멤버 데이터를 비트열 단위로 똑같이 복사함

(메모리 영역 값을 그대로 복사)

 

ex (a1 클래스를 얕은 복사, b 클래스는 동적 할당, a 클래스와 b 클래스는 생명 주기를 같이 함)

Stack : a1 [ q 0x1000 ] - Heap 0x1000 b [     ]

Stack : a2 [ q 0x1000 ]

Stack : a3 [ q 0x1000 ]

메모리 영역을 그대로 복사해오기 때문에 동일한 주소 값을 가지고 있다.

위와 같은 조건일 때 a1, 2, 3가 전부 동일한 Heap 영역의 b 클래스를 가리키고 있기 때문에 b 클래스는 생성자 호출을

한 번만 하게 되고 소멸자 호출은 세 번을 하게 되면서 에러가 발생한다.

 


 

깊은 복사 (Deep Copy)

멤버 데이터가 참조(주소) 값이라면 데이터를 새로 만들어준다.

(원본 객체가 참조하는 대상까지 새로 만들어서 복사)

 

ex

Stack : a1 [ q 0x1000 ] - Heap 0x1000 b [     ]

Stack : a2 [ q 0x2000 ] - Heap 0x2000 b [     ]

Stack : a3 [ q 0x3000 ] - Heap 0x3000 b [     ]

얕은 복사의 상황을 한 번에 해결할 수 있다. a 클래스들은 각각의 서로 다른 b 클래스 객체를 

가지게 된다. 

 

깊은 복사를 해주기 위해서는 복사 대입 연산자를 재정의해서 사용하면 된다.

 


 

복사 생성자 행동 절차

 

1. 암시적 복사 생성자

 - 부모 클래스가 있다면 부모 클래스의 복사 생성자 호출

 - 멤버 클래스(포인터가 아닌 일반적으로 클래스를 가지고 있는 상태를 말함)의 복사 생성자 호출

 - 두 경우가 모두 아니고 멤버의 타입이 기본 타입이라면 메모리 복사, 즉 얕은 복사를 하게 된다.

 

2. 명시적 복사 생성자

 - 부모 클래스의 기본 생성자 호출

 - 멤버 클래스의 기본 생성자 호출

 

중요한 포인트는 명시적으로 복사 생성자를 정의하게 되면 그 이후부터는 프로그래머가 모든

복사와 관련되서 핸들링해야 한다는 점이다. 암시적 때처럼 컴파일러가 자동적으로 복사 생성자를 호출해주지

않기 때문에 프로그래머는 따로 복사 생성자를 호출해야 한다. 만약 이 부분을 놓치게 되면 복사가 완전히

이루어지지 않고 짤리는 부분이 생기거나 할 수 있다.

 


 

복사 대입 연산자 행동 절차

 

1. 암시적 복사 대입 연산자

 - 부모 클래스의 복사 대입 연산자 호출

 - 멤버 클래스의 복사 대입 연산자 호출

 - 멤버가 기본 타입일 경우 메모리 복사(얕은 복사)

 

2. 명시적 복사 대입 연산자

 -  프로그래머가 모든 걸 알아서 핸들링해야 함