클래스의 복사생성자는 클래스를 생성하면서 다른 객체를 레퍼런스로 전달받아 새로운 객체를 생성하는 것을 말한다.
다음과 같이 클래스가 존재한다고 하자.
template <typename T>
class CTest {
private :
T m_i;
public:
void push_data(const T& _data);
};
template<typename T>
void CTest<T>::push_data(const T& _data)
{
m_i = _data;
}
해당 클래스는 데이터를 전달 받아 메소드를 활용하여 맴버변수를 변경시킨다.
이 객체를 생성해 보자
int main() {
CTest<int> t1;
CTest<int> t2;
// 생성된 객체에 맴버변수의 값을 변경시킨다.
t1.push_data(20);
return 0;
}
int타입으로 객체를 2개 생성하였다.
다음 t2객체에 t1을 대입시켜보자
int main() {
CTest<int> t1;
CTest<int> t2;
// 생성된 객체에 맴버변수의 값을 변경시킨다.
t1.push_data(20);
t2 = t1;
return 0;
}
생성된 객체끼리 대입이 이루어져 t2의 맴버변수가 20으로 바뀐 것을 debug 모드에서 알 수 있다.
생성된 객체끼리 대입 연산이 가능한 이유는 객체가 생성될때 default 대입 연산자가 자동으로 생성되어 대입연산이 가능하다.
객체 생성 -> 맴버변수 초기화 -> 다른 객체의 맴버변수 복사 -> 값 할당
위와 같은 과정으로 생성된 객체는 다소 비효율적으로 보인다.
복사생성자를 만들면 객체 생성과 동시에 다른 객체의 맴버변수를 할당 할 수 있다.
참고
복사생성자도 구현이 없으면 default로 생성된다.
복사생성자는 다음과 같이 구현할 수 있다.
template <typename T>
class CTest {
private :
T m_i;
public:
//복사생성자
//복사 생성자는 매개변수를 생성된 클래스 객체를 레퍼런스로 받음.
CTest(const CTest& _copyClass)
: m_i(_copyClass.m_i) // 초기식에도 멤버변수에 전달한다.
{
}
//복사생성자를 만들면 컴파일러가 default 생성자를 제공하지 않음으로 직접 구현해야함.
CTest()
: m_i(0)
{
}
public:
void push_data(const T& _data);
};
복사생성자를 정의하면 기본생성자도 정의해야한다.
이는 복사생성자를 정의하는 순간 컴파일러가 생성자에 대한 오버로딩을 하고자 하는 의도라 파악하여 기본생성자를 만들지 않는다.
정의된 복사생성자는 다음과 같이 사용할 수 있다.
int main() {
CTest<int> t1;
CTest<int> t2;
// 생성된 객체에 맴버변수의 값을 변경시킨다.
t1.push_data(20);
// 생성된 객체를 대입하는 방식,
// 대입 연산자는 별도로 정의 하지 않으면 이미 defalut 대입 연산자로 생성된다..
t2 = t1;
//t2에게 t1의 변경된 값이 잘 전달된다.
// 객체를 생성하면서 복사생성자를 이용하여 객체를 생성함.
CTest<int> t3(t1);
// 아래와 같이 생성과 동시에 대입연산자를 이용하면 복사생성자로 컴파일러가 인식하여
// 복사생성자를 실행한다.
CTest<int> t4 = t1;
return 0;
}
클래스에 생성자 매개변수를 다른 객체를 전달하거나 대입연산을 통해 복사생성자 실행을 할 수 있다.