프로그래밍에서 객체나 자료구조를 복사할 때, 단순히 값만 복사하는지, 아니면 내부 참조 구조까지 새로 복제하는지에 따라 결과가 달라진다. 이를 각각 Shallow Copy(얕은 복사), Deep Copy(깊은 복사)라고 한다.
Shallow Copy(얕은 복사)는 객체의 1차 필드(외부 구조)만 복사하고, 내부에 참조하는 포인터/주소값은 그대로 공유한다.
| 즉, 복사된 객체와 원본 객체가 같은 메모리 공간을 참조한다.
#include <iostream>
using namespace std;
class Shallow {
public:
int* data;
Shallow(int val) {
data = new int(val);
}
// 복사 생성자 (얕은 복사)
Shallow(const Shallow& other) {
data = other.data;
}
void print() {
cout << "Value: " << *data << endl;
}
};
int main() {
Shallow a(10);
Shallow b = a; // 얕은 복사
*b.data = 99;
a.print(); // Value: 99 (같은 메모리를 참조)
b.print(); // Value: 99
}
| 문제점: 하나를 수정하면 둘 다 바뀌는 의도치 않은 부작용 발생
Deep Copy(깊은 복사)는 객체가 참조하고 있는 내부의 값들도 모두 새롭게 복사합니다. 즉, 독립된 메모리 공간을 가지게 된다.
#include <iostream>
using namespace std;
class Deep {
public:
int* data;
Deep(int val) {
data = new int(val);
}
// 복사 생성자 (깊은 복사)
Deep(const Deep& other) {
data = new int(*other.data);
}
void print() {
cout << "Value: " << *data << endl;
}
};
int main() {
Deep a(10);
Deep b = a; // 깊은 복사
*b.data = 99;
a.print(); // Value: 10
b.print(); // Value: 99
}
| 장점: 각 객체가 독립된 공간을 가지므로 서로 영향 X

| C++에서는 직접 복사 생성자 / 대입 연산자를 구현하여 Deep Copy를 명시적으로 처리하는 경우가 많다.
std::vector, std::string 등 C++ STL 컨테이너는 대부분 Deep Copy를 지원한다.
단, 포인터를 요소로 갖는 컨테이너는 Shallow Copy처럼 동작할 수 있으므로 주의해야 한다.
vector<int*> a = { new int(1), new int(2) };
vector<int*> b = a;
*b[0] = 100;
cout << *a[0]; // 100 (얕은 복사처럼 동작)
Shallow Copy는 빠르고 메모리를 적게 쓰지만, 의도치 않은 공유가 위험할 수 있다.
Deep Copy는 안전하지만, 성능 비용이 따른다.
따라서 상황에 따라 어떤 방식이 적절한지 판단하고, 필요하다면 직접 복사 생성자나 대입 연산자를 정의해야 한다.