얕은 복사(Shallow Copy) vs 깊은 복사(Deep Copy)

DevBison·2025년 11월 20일

얕은 복사는 ‘주소만 복사’, 깊은 복사는 ‘내용까지 새로 복사’하는 차이다.

C++에서 복사 생성자를 어떻게 구현하느냐에 따라 객체가 ‘얕게 복사’될 수도 있고 ‘깊게 복사’될 수도 있다.
특히 포인터 멤버(int*)를 가진 클래스라면 둘의 차이가 결과에 큰 영향을 준다.


1. 얕은 복사 (Shallow Copy)

개념

  • 객체의 멤버 값을 그대로 복사한다.
  • 포인터 멤버가 있다면 주소값만 복사한다.
  • 즉, 원본 객체와 복사된 객체가 같은 메모리(data)를 공유하게 된다.
  • 그래서 하나를 수정하면 둘 다 값이 변한다.

예시 코드

class MyArray {
public:
    int size;
    int* data;

    MyArray(int size) {
        this->size = size;
        data = new int[size];
    }

    // 얕은 복사 생성자
    MyArray(const MyArray& other) {
        this->size = other.size;
        this->data = other.data;   // 주소값만 복사됨
    }
};

문제점

  • 두 객체가 같은 data[]를 바라봄 → 의도치 않은 변화 발생
  • 하나가 소멸되며 delete[] 호출 시 → 다른 객체는 댕글링 포인터(dangling pointer)가 됨

2. 깊은 복사 (Deep Copy)

개념

  • 객체가 가진 모든 데이터 자체를 새로 복사한다.
  • 포인터 멤버가 있을 경우
    새로운 메모리(new)를 만들고
    → 원본 배열의 내용을 하나씩 복사한다.
  • 복사된 객체는 완전히 독립적인 메모리를 가진다.

예시 코드

class MyArray {
public:
    int size;
    int* data;

    MyArray(int size) {
        this->size = size;
        data = new int[size];
    }

    ~MyArray() {
        delete[] data;
    }

    // 깊은 복사 생성자
    MyArray(const MyArray& other) {
        this->size = other.size;
        this->data = new int[size];      // 새 메모리 확보

        for (int i = 0; i < size; i++) {
            this->data[i] = other.data[i];   // 데이터 자체 복사
        }
    }
};

장점

  • 복사된 객체는 원본과 완전히 분리된다.
  • 서로 영향을 주지 않는다.
  • 소멸자에서도 각자 자기 메모리만 관리하면 된다.

핵심 차이 요약

구분얕은 복사깊은 복사
포인터 복사 방식주소값만 복사새 메모리 생성 후 값 복사
두 객체 관계같은 데이터를 공유완전히 분리된 개별 객체
수정 시 영향서로에게 영향 있음서로 영향 없음
delete 실행 시 문제매우 큰 문제 발생 (중복 해제 위험)안전

결론

  • 포인터나 동적 메모리를 가진 클래스라면 거의 무조건 깊은 복사를 구현해야 한다.
  • 얕은 복사는 매우 위험하고, 특별한 목적이 있는 경우에만 사용한다.
profile
응애 개발자

0개의 댓글