본문 바로가기

C++

복사 생성자(Copy Constructor)

클래스명(const 클래스명& _이름) 타입이 복사 생성자를 호출하는 인자 타입이다.

복사 생성자는 클래스가 객체화 될 때 기본적으로 생성되는 생성자이다. 즉 복사 생성자를 사용자가 정의하지 않아도

기본적으로 만들어지는 생성자라는 의미다. 즉, 인자로 들어오는 객체의 멤버들을 자신의 멤버들에게 복사하는 일을

담당한다.

class ClassA
{
public:
    ClassA()  {}
    ClassA(const ClassA& _copyCls)
    {
        cout << "복사 생성자" << endl;
    }
    ~ClassA() {}
};
class ClassA
{
public:
    ClassA()  {}
    ClassA(const ClassA& _copyCls)
    {
        cout << "복사 생성자" << endl;

        // 첫 번째 방법
        *this = _copyCls;

        // 두 번째 방법
        m_iData   = _copyCls.m_iData;
        m_strData = _copyCls.m_strData;
    }
    ~ClassA() {}

public:
    int m_iData = 0;
    string m_strData = "";
};

int main()
{
    ClassA instA = ClassA();
    instA.m_iData = 10;
    instA.m_strData = "Copy Constructor";

    ClassA instB = ClassA(instA); // 복사 생성자 호출
    cout << "iData : " << instB.m_iData << endl;
    cout << "strData : " << instB.m_strData.c_str() << endl;

    return 0;    
}

결과
iData : 10
strData : Copy Constructor

생성자 , 복사 생성자, 인자가 있는 생성자의 의미? 생성자 오버로딩(Overloading)

생성자는 위 처럼 오버로딩이 일어난다. 그럼 복사 생성자는 사용자가 만들지 않았을 때 기본적으로 컴파일러가

만들어주는 복사 생성자는 내부적으로 '얕은 복사'가 이뤄진다. 하지만 복사 생성자를 오버로딩하여 사용할 경우

재정의 의미를 가지기 때문에 복사 작업을 직접 구현해야 한다.

 

(=)대입 연산자 오버로딩

복사 생성자와 헷갈릴 수 있는 부분인데 이미 생성된 객체에 대하여 대입 하는건 복사 생성자 호출이 아니다.

생성자는 말 그대로 생성할 때고 대입은 이미 생성된 값에 대하여 대입할 때 이뤄지는 것이다.

대입 연산자 오버로딩도 말 그대로 = 연산자를 재정의 한다는 의미기 때문에 기본 대입 연산자는 내부적으로

'얕은 복사'가 이뤄지지만 오버로딩하여 사용할 경우에는 생성자 오버로딩과 마찬가지로 직접 구현해야 한다.

 

복사 생성자가 호출되는 시점

1. 객체가 생성될 때 다른 객체를 이용하여 초기화할 경우

2. Call By Value 형식으로 인자를 받았을 경우

3. Value(값) 형식으로 반환할 경우

class ClassA
{
public:
    ClassA() {}
    ClassA(const ClassA& _cls)
    {
        cout << "복사 생성자" << endl;
    }

public:
    void CallByValueType(const ClassA _cls)
    {
    }

    ClassA ReturnTypeValue()
    {
        ClassA cls = ClassA();
        return cls;
    }
};

int main()
{
    ClassA clsA = ClassA();
	
    // 객체가 생성될 때 다른 객체를 이용하여 초기화할 경우
    ClassA clsB = ClassA(clsA);

    // Call By Value 형식으로 인자를 받았을 경우
    clsA.CallByValueType(clsB);

    // Value(값) 형식으로 반환할 경우
    ClassA clsC = clsB.ReturnTypeValue();

    return 0;
}