C++언어 공부/개념 공부

2024.01.28 C++ 추가 공부 [얕은 복사, 깊은 복사]

코딩입문시작 2024. 1. 28. 18:00

깊은 복사와 얕은 복사

 

객체는 다른 객체를 참조할 수 있는데 이럴 경우에 깊은 복사인가, 얕은 복사인가에 따라 결과값이 달라질 수 있으니 주의해야 한다. 복사를 한다는 것은 기존 객체와 같은 값은 가진 새로운 객체로 만드는 것이다.

 

※ 근데! 객체들은 멤버를 가지고 있고 그 멤버들은 값일 수도 있고, 참조 형식일 수도 있다.

 


[ 참고 ]

모든 데이터 타입은 값 타입(value type) 또는 참조 타입(reference type)을 가진다.

  • 값 타입(Value type) : 각각의 고유의 메모리를 소유한다. 스위프트에서 struct, enum, array, tuples 들이 해당 타입에 속한다.
  • 참조 타입(Reference type) : 생성된 인스턴스들은 주소값을 공유한다. 스위프트에서 class가 해당 타입에 속한다.

 

→ 바로 이 객체들이 가진 값 형식과 참조 형식의 복제 방식에 따라 얕은 복사와 깊은 복사의 개념이 나뉘어지게 된다.

 

얕은 복사 (Shallow Copy)

  • 얕은 복사는 객체가 가진 멤버들의 값을 새로운 객체로 복사하는데 만약 객체가 참조타입의 멤버를 가지고 있다면 참조값만 복사가 된다.얕은 복사는 아주 최소한만 복사를 한다. 값을 복사한다 하더라도, 인스턴스가 메모리에 새로 생성되지 않는다. 값 자체를 복사하는 것이 아니라 주소값을 복사하여 같은 메모리를 가리키기 때문이다.
  • 새로운 인스턴스를 생성하지 않기 때문에 깊은 복사보다 상대적으로 빠르다. reference type을 복사하는 경우 얕은 복사가 일어난다.

 

기본 복사 생성자 이용

 

A클래스의 이름을 YJ 나이를 20으로 변경했을 때 A클래스를 얕은 복사한 B클래스의 이름까지 바뀐 걸 확인할 수 있다. 

 

기본 복사 생성자를 이용했으니 이번에는 얕은 복사 생성자 코드를 이용하여 알아보자.

얕은 복사 생성자 코드
얕은 복사 생성자 코드

실행을 해보면, 빌드시 복사 생성자에 중단점이 걸린걸 확인할 수 있다. 디폴트 복사 생성자는 얕은 복사를 사용하는 걸로 확인된다. 이런 방식에 문제점이 무엇일까? 

new char[3] 동적 할당을 하고 있어서 메모리 누수(릭)가 체크되고 있는데 TestClass는 A_Class, B_Class 두 개를 만들었는데 3 bytes long 만큼만 체크가 되고 있다. 소멸자에서 메모리누수(릭)를 delete 해보자. 

디버깅에 오류가 생긴다... TestClass는 A_Class, B_Class 두 개를 만들었는데 얕은 복사를 해서 메모리 참조를 하고있으니 삭제한 메모리를 한번 더 삭제하려고 하니까 실행에 오류가 생기는 것이다. 그럼 깊은 복사 생성자를 만들어 보자.

 

깊은 복사 (Deep Copy)

  • 깊은 복사 또는 전체 복사
  • 얕은 복사와는 달리, 객체가 가진 모든 멤버(값과 참조형식 모두)를 복사하는 것이다.
  • 객체가 참조 타입의 멤버를 포함할 경우 참조값의 복사가 아닌 참조된 객체 자체가 복사되는 것을 말한다. 

A 클래스의 이름만 수정되고 B 클래스의 이름은 그대로 남는 것을 확인할 수 있다. 메모리 누수(릭)도 남지 않고 깔끔하게 프로그램이 종료되었다. 

 

그럼 이쯤되면, 필자도 생각했지만 이걸 읽는 사람도 생각해 볼 것이다.

왜 ? 얕은 복사와 깊은 복사를 나누고 얕은 복사를 사용할 일이 있나? 아직 필자도 공부중에 있어, 잘 알지는 못한다... 더 공부해서 알게되면 여기에 남길 예정이다. 아는 사람은 여기에 댓글로 알려주시면 감사하겠습니다. (꾸벅 ...)

 

구글링을 통해 알아본 바로는...

1. 얕은 복사과 깊은 복사 모두 객체를 복사하긴한다. 하지만 얕은 복사의 경우 저장된 데이터들까지 복사를 하진 않기때문에 서로가 영향을 주고 받으며, 완전히 독립적인 객체로 만들기 위해서는 깊은 복사가 필요한 것이다.

 

2. 이처럼 얕은 복사는 간단하지만 멤버변수에 따른 문제점이 발생하는 것을 고려해야 한다. 이런 문제를 해결하기 위해 나온 것이 깊은 복사 (deep copy) 다. 얕은 복사는 디폴트 복사 생성자인 반면, 깊은 복사는 복사 생성자를 재정의함으로써 원하는 멤버 변수만 복사를 해주는 형식이다. 그래서 얕은 복사의 문제점을 해결할 수 있다.

 

참고 사이트 : [C++] 깊은 복사(Deep Copy)와 얕은 복사 (Shallow Copy), 복사 생성자 (tistory.com)

 

[C++] 깊은 복사(Deep Copy)와 얕은 복사 (Shallow Copy), 복사 생성자

인트로 깊은 복사와 얕은 복사를 학습하기 전에 알아두면 좋은 지식은 복사 생성자(Copy Constructor)이다. 복사 생성자란 다른 객체로부터 값을 복사해서 새로운 객체를 초기화하는데 사용되는 생

kangworld.tistory.com

 

참고사이트 : C++ - 복사생성자 (얕은복사와 깊은복사) (sosal.kr)

 

C++ - 복사생성자 (얕은복사와 깊은복사)

/* * http://sosal.tistory.com/ * made by so_Sal */ 복사생성자에 관한 문제를 보고 정리해볼겸 트랙백 날립니다 ^-^ C++에는 2가지 종류의 변수 초기화 방법을 제공합니다. int main(){ int a = 10;

sosal.kr

 

참고사이트 : [C++ 기본 공부정리] 14-4. OOP - 생성자(constructor) (tistory.com)

 

※ 정리 

간략하게 설명하면 얕은 복사는 C++에서 같은 타입의 객체를 복사할 때, 그 객체의 멤버 변수가 데이터를 가르키는 포인터라면 데이터 자체를 복사하는 것이 아닌 복사하고자 하는 객체의 멤버 변수가 가르키는 데이터를 참조하는 형식으로 복사가 진행됨을 뜻한다.

 

깊은 복사는 반대로 참조하는 방식이 아닌 가르키는 데이터 그 자체를 복사하는 것이다..