ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C++] 깊은 복사와 얕은 복사
    프로그래밍/C & C++ 2024. 7. 5. 16:56
    728x90
    반응형

    깊은 복사(Deep Copy)와 얕은 복사(Shallow Copy)는 객체를 복사할 때 자원을 어떻게 처리할 것인가에 대한 두 가지 접근 방식입니다. 이 두 방식의 차이점을 이해하는 것은 특히 동적 메모리를 사용하는 프로그램에서 매우 중요합니다.

    1. 얕은 복사 (Shallow Copy)

    얕은 복사는 객체의 멤버 데이터를 그대로 복사합니다. 기본 데이터 타입(int, float 등)이나 복사가 간단한 멤버는 문제가 없지만, 포인터 같은 멤버를 포함한 객체에서는 문제가 발생할 수 있습니다. 얕은 복사는 원본 객체와 복사된 객체가 같은 자원(예: 메모리)을 공유하게 됩니다.

    예시:

    #include <iostream>
    
    class ShallowCopy {
    public:
        int* data;
    
        // 생성자
        ShallowCopy(int value) : data(new int(value)) {}
    
        // 복사 생성자 (얕은 복사)
        ShallowCopy(const ShallowCopy& other) : data(other.data) {}
    
        // 소멸자
        ~ShallowCopy() {
            delete data;
        }
    };
    
    int main() {
        ShallowCopy obj1(42);
        ShallowCopy obj2 = obj1; // 얕은 복사
    
        std::cout << "obj1.data: " << *(obj1.data) << std::endl;
        std::cout << "obj2.data: " << *(obj2.data) << std::endl;
    
        *(obj2.data) = 100; // obj2의 data를 변경하면 obj1의 data도 변경됨
        std::cout << "After modification:" << std::endl;
        std::cout << "obj1.data: " << *(obj1.data) << std::endl;
        std::cout << "obj2.data: " << *(obj2.data) << std::endl;
    
        return 0;
    }

    위 예시에서 ShallowCopy 클래스의 얕은 복사 생성자는 원본 객체와 복사된 객체가 같은 data 포인터를 공유하게 됩니다. 이는 한 객체가 자원을 해제할 때 다른 객체의 자원이 유효하지 않게 되는 문제를 일으킬 수 있습니다.

    2. 깊은 복사 (Deep Copy)

    깊은 복사는 객체의 멤버 데이터를 복사할 뿐만 아니라, 포인터가 가리키는 동적 메모리까지 새로 할당하여 복사합니다. 따라서 원본 객체와 복사된 객체는 독립적인 자원을 가지게 되어, 한 객체의 변경이 다른 객체에 영향을 미치지 않습니다.

    예시:

    #include <iostream>
    
    class DeepCopy {
    public:
        int* data;
    
        // 생성자
        DeepCopy(int value) : data(new int(value)) {}
    
        // 복사 생성자 (깊은 복사)
        DeepCopy(const DeepCopy& other) : data(new int(*(other.data))) {}
    
        // 소멸자
        ~DeepCopy() {
            delete data;
        }
    };
    
    int main() {
        DeepCopy obj1(42);
        DeepCopy obj2 = obj1; // 깊은 복사
    
        std::cout << "obj1.data: " << *(obj1.data) << std::endl;
        std::cout << "obj2.data: " << *(obj2.data) << std::endl;
    
        *(obj2.data) = 100; // obj2의 data를 변경해도 obj1의 data는 영향받지 않음
        std::cout << "After modification:" << std::endl;
        std::cout << "obj1.data: " << *(obj1.data) << std::endl;
        std::cout << "obj2.data: " << *(obj2.data) << std::endl;
    
        return 0;
    }

    위 예시에서 DeepCopy 클래스의 깊은 복사 생성자는 새로운 메모리를 할당하고, 원본 객체의 데이터를 복사합니다. 따라서 원본 객체와 복사된 객체는 독립적인 data 포인터를 가지게 됩니다.

    3. 깊은 복사와 얕은 복사의 비교

    특징 얕은 복사 깊은 복사
    메모리 공유 아니오
    성능 빠름 느림
    안전성 낮음 (복사본과 원본이 같은 자원을 공유) 높음 (복사본과 원본이 독립적인 자원 사용)
    복잡도 낮음 높음

    4. 이동 의미론과의 비교

    이동 의미론은 깊은 복사와 얕은 복사 사이의 절충안으로, 객체의 소유권을 이동시켜 성능을 최적화합니다. 이동 의미론을 사용하면 복사의 오버헤드를 줄이면서도 자원을 안전하게 관리할 수 있습니다.

    깊은 복사와 얕은 복사의 차이점을 이해하고 적절히 사용하는 것은 성능 최적화와 메모리 관리에서 매우 중요합니다. 필요에 따라 이동 의미론을 함께 사용하면 더 효율적인 프로그램을 작성할 수 있습니다.

    728x90
    반응형
Designed by Tistory.