복사 생성자는 객체의 복사본을 생성할 때 호출되는 생성자이다.

CMYData a

CmyData b(a)

 

이처럼 원본 a의 복사본을 만들때 복사 생성자가 불린다.

문법은 클래스이름(const 클래스이름 &rhs) 처럼 사용한다.

 

#include <iostream>
using namespace std;

class CMYData
{
public:
	CMYData() { cout << "기본 생성자" << endl; };
	CMYData(const CMYData &rhs) 
	{
		this->m_nData = rhs.m_nData;
		cout << "복사 생성자" << endl;
	};

	int GetData(void) { return m_nData; };
	void SetData(int nParam) { m_nData = nParam; };

private:
	int m_nData;
};

int main(void)
{
	CMYData a;
	a.SetData(10);

	CMYData b(a);
	cout << b.GetData() << endl;
	return 0;
}

// 출력값
// 기본 생성자
// 복사 생성자
// 10

이런 식으로 CMYData b(a)와 같은 상황일 때 복사 생성자가 불린다. 여기서 rhs는 원본 즉 a 인스턴스의 참조 변수이다.

이것만 봐서는 도대체 복사 생성자가 왜 중요한지 모르겠다. 하지만 매개변수로 사용되는 복사 생성자를 보면 성능에 대해서 아주 중요한 이야기가 나온다. 결론은 가능하면 무조건 참조형으로 받자! 왜냐? 인스턴스가 하나 더 생성 되니깐

참조형으로 받겠다는 말은 주소로 넘기자 이말이다(call by reference)

 

매개변수로 사용되는 복사 생성자
#include <iostream>
using namespace std;

class CMYData
{
public:
	CMYData(int nParam)
		:m_nData(nParam)
	{
		cout << "기본 생성자" << endl; 
	};

	CMYData(const CMYData &rhs) 
		:m_nData(rhs.m_nData)
	{
		cout << "복사 생성자" << endl;
	};

	int GetData(void) { return m_nData; };
	void SetData(int nParam) { m_nData = nParam; };

private:
	int m_nData;
};

void TestFunc(CMYData param)
{
	cout << "TestFunc" << endl;
	param.SetData(20);
}

int main(void)
{
	CMYData a(10);
	TestFunc(a);
	cout << a.GetData() << endl;

	return 0;
}

//출력값
//기본 생성자
//복사 생성자
// TestFunc
// 10

다 집어치우고 main함수에서 TestFunc(a)를 호출하면 복사 생성자가 호출된다 왜냐하면 TestFunc의 매개변수는 CMYData param이기 때문이다. 그러니깐 param은 CMYData의 새로운 인스턴스다. 인스턴스를 하나 더 만들었다.

골때린다. 그리고 그 새로운 인스턴스에 20값을 집어 넣어놓고는 인스턴스가 삭제됐다(스택 프레임 종료). 그러니 a는 여전히 10일 수 밖에.. 아무것도 못하고 성능 낭비 메모리 낭비만 하고 사라지는 거지같은 함수 TestFunc다. 이것을 아주 우아하게 바꾸려면 앞에 & 참조만 붙여주면 된다.

바로 void TestFunc(CMYData &param)이렇게! 이렇게 해야 call by reference로 주소만 넘긴다! 객체를 생성하지도 않고 성능도 아주 좋다.

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

C++ 대입 연산자  (0) 2020.02.02
C++ 깊은복사 얕은복사  (0) 2020.02.02
C++ this 포인터  (0) 2020.02.01
C에서 C++ 객체지향의 변환 과정  (0) 2020.01.28
C++ 참조자 형식(reference)  (0) 2020.01.27

+ Recent posts