본문 바로가기

C++

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

복사 생성자가 호출될 시 사용자가 직접 오버로딩 하지 않았다면 기본 복사 생성자가 자동으로 호출된다.

이때, 일어나는 복사는 얕은 복사가 일어난다. 그럼 얕은 복사와 깊은 복사의 차이는 무엇인가?

 

얕은 복사(Shallow Copy)

객체가 가진 멤버들의 값을 복사될 객체의 멤버 값으로 1:1 복사가 된다. 만약 어떤 메모리를 참조하고 있는 타입이 

멤버에 있는 경우는 값과 멤버가 복사되는 것이 아니라 참조 하고 있는 메모리의 값을 복사하게 된다.

 


깊은 복사(Deep Copy)

값만의 복사가 값과 참조하고 있는 메모리까지 전부 복사를 의미한다. 위 얕은 복사에서 int* m_pAdress를 

두개의 객체가 공유하는 형식이 아닌 각 객체마다 참조하고 있는 메모리를 별도로 가지고 있는걸 의미한다. 하지만 이런

작업을 기본적으로 제공해주는건 아니다. 직접 복사 생성자 내부에서 구현해야한다.

 


얕은 복사(Shallow Copy) 깊은 복사(Deep Copy) 전체 코드

class ClassA 
{
public:
    ClassA() : 
        m_iData(0),
        m_strData(),
        m_pAdress(nullptr)
    {
        m_iData    = 10;
        m_pAdress  = &m_iData;
        size_t len = sizeof("Hello");
        m_strData  = new char[len];
        strcpy_s(m_strData, len, "Hello");
    }

    // 얕은 복사(Shallow Copy)
    /*ClassA(const ClassA& _copyInst)
    {
        *this = _copyInst;
    }*/

    // 깊은 복사(Deep Copy)
    // 깊은 복사는 반드시 직접 구현해줘야한다.
    ClassA(const ClassA& _copyInst)
    {
        m_iData = _copyInst.m_iData;
        m_pAdress = &m_iData;
		
        // 코드영역에 있는 문자열 메모리 공유를 동적할당으로 해결
        size_t len = sizeof("Hello");
        m_strData  = new char[len];
        strcpy_s(m_strData, len, "Hello");
    }

    ~ClassA() 
    {
        if (m_strData != nullptr)
        {
            delete[] m_strData;
        }
    }

public:
    int   m_iData;
    int*  m_pAdress;
    char* m_strData;
};

int main()
{
    ClassA clsA = ClassA();
    ClassA clsB = ClassA(clsA);

    // A 
    printf("A =================================================================\n");
    printf("1. m_iData   주소 값 : %p\n", &(clsA.m_iData));
    printf("2. m_pAdress 주소 값 : %p, 내부가 가리키는 주소 : %p\n", &(clsA.m_pAdress), clsA.m_pAdress);
    printf("3. m_strData가 가리키는 주소 값 : %p\n\n", clsA.m_strData);

    // B
    printf("B =================================================================\n");
    printf("1. m_iData   주소 값 : %p\n", &(clsB.m_iData));
    printf("2. m_pAdress 주소 값 : %p, 내부가 가리키는 주소 : %p\n", &(clsB.m_pAdress), clsB.m_pAdress);
    printf("3. m_strData가 가리키는 주소 값 : %p\n\n", clsB.m_strData);    
    
    return 0;
}

객체를 복사할 때 메모리를 참조하여 사용하는지?에 따라서 얕은 복사, 깊은 복사를 써야하는지 잘 판단하여 사용하자. 

'C++' 카테고리의 다른 글

static ?  (0) 2019.07.17
C++ Type Cast  (0) 2019.07.17
복사 생성자(Copy Constructor)  (0) 2019.07.11
레퍼런스(Reference)와 포인터(Pointer) 차이  (0) 2019.07.10
다중 상속(Diamond of Death)의 문제점  (0) 2019.07.10