[05-1] '복사 생성자'와의 첫 만남

김민성·2022년 7월 21일
post-thumbnail

복사생성자를 왜 정의해야 하는 걸까?
대입연산 즉, 새로운 객체를 기존의 객체로 초기화하는 대입연산의 결과를 우리가 정의하게끔 하도록 하기 위해서이다.

C++ 스타일의 초기화


위의 두 가지 초기화 방식은 결과적으로 동일하다.

그렇다면 이야기를 객체의 생성으로 옮겨가 보자.

위의 코드 중에서 다음 문장은 객체의 생성 및 초기화를 연상시킨다.

SoSimple sim2=sim1;

대입연산의 의미처럼 실제 sim1과 sim2간의 대 멤버의 복사가 일어난다!

복사할 때, '디폴트 복사 생성자'가 자동 삽입된다. 멤버 대 멤버의 복사가 이루어지도록 정의가 되어 삽입된다.

SoSimple sim2(sim1);

SoSimple sim2(sim1);

이 문장의 의미는 다음과 같다.

  • SoSimple형 객체를 생성해라.
  • 객체의 이름은 sim2로 정한다.
  • sim1을 인자로 받을 수 있는 생성자의 호출을 통해서 객체생성을 완료한다.

SoSimple sim2=sim1 은 묵시적으로 SoSimple sim2(sim1) 으로 해석이 된다.

그런데 앞서 정의한 SoSimple 클래스에는 이러한 유형의 생성자가 정의되어 있지 않았다. 그럼 혹시 앞서 제시한 클래스와 main 함수는 제대로 컴파일되지 않는, 문제가 있는 코드는 아닐까? 이에 대한 이해를 위해 먼저 다음예제를 관찰해보자.

ClassInit.cpp

#include <iostream>
using namespace std;

class SoSimple
{
private:
	int num1;
	int num2;
public:
	SoSimple(int n1, int n2) 
		: num1(n1), num2(n2)
	{
		// empty
	}

	SoSimple(SoSimple &copy)
		: num1(copy.num1), num2(copy.num2)
	{
		cout<<"Called SoSimple(SoSimple &copy)"<<endl;
	}

	void ShowSimpleData()
	{
		cout<<num1<<endl;
		cout<<num2<<endl;
	}
};

int main(void)
{
	SoSimple sim1(15, 30);
	cout<<"생성 및 초기화 직전"<<endl;
	SoSimple sim2=sim1;
	cout<<"생성 및 초기화 직후"<<endl;
	sim2.ShowSimpleData();
	return 0;
}
생성 및 초기화 직전
Called SoSimple(SoSimple &copy)
생성 및 초기화 직후
15
30

위 예제에서 다음 부분을 살펴보자.

SoSimple(SoSimple &copy)
		: num1(copy.num1), num2(copy.num2)
	{
		cout<<"Called SoSimple(SoSimple &copy)"<<endl;
	}

실제로 위의 복사생성자가 완전한 복사생성자가 되기 위해서는 const 선언을 넣어줘야 한다. 멤버 대 멤버의 복사에 사용되는 원본을 변경시키는 것은 복사의 개념을 무너뜨리는 행위가 된다.

그리고 이니셜라이저를 선언해주어 멤버 대 멤버 간의 복사가 되도록 정의를 해 복사생성자가 자동으로 생성되었는데, 이때 생긴 복사생성자가 바로 '디폴트 복사생성자'이다.

자동으로 삽입이 되는 디폴트 복사 생성자


복사 생성자를 정의하지 않으면, 멤버 대 멤버의 복사를 진행하는 디폴트 복사 생성자가 삽입된다.

변환에 의한 초기화! 키워드 explicit으로 막을 수 있다!


위와 같은 유형의 변환이 마음에 들지 않는다면,
이러한 묵시적 형 변환은 복사 생성자를 explicit 으로 선언하면 막을 수 있다.

그리고 이러한 문장의 묵시적 변환은 복사 생성자에서만 일어나는 게 아니다. 전달인자가 하나인 생성자가 있다면, 이 역시 묵시적 변환이 발생한다.

여기에 explicit을 선언하면 "AAA obj=3;"으로 객체 생성이 불가능하고, "AAA obj(3);"의 형태로만 객체 생성이 가능하다.

profile
다양한 활동을 통해 인사이트를 얻는 것을 즐깁니다. 저 또한 인사이트를 주는 사람이 되고자 합니다.

0개의 댓글