복사 생성자에 대해 이야기하기 전에 C++ 스타일에 독특한 초기화 방식을 먼저 보겠습니다.
int n = 20;
int &nref = n;
int s(30);
int &sref(s);
위에 두 문장과 아래 두 문장은 동일한 기능을 수행합니다.
이 전 블로그에 멤버 이니셜라이저에 대해 이야기했는데 멤버 이니셜라이저 과정에서 위에 형태를 찾아볼 수 있습니다.
이어서 다음의 코드를 보겠습니다.
int main()
{
Simple sim1(15,20);
Simple sim2 = sim1;
sim2.SHowSimpledata();
}
Simple 클래스에 인자값을 2개를 받는 생성자를 만들었다고 가정해 보면, sim1이라는 객체는 생성과 동시에 인자값을 전달하며 생성자를 호출하였습니다.
하지만 sim2 객체는 생성시 생성자 호출이 없이 대입연산자만 진행이 되었습니다.
그렇다면 sim2는 어떠한 방식으로 생성이 되었을지 알아보겠습니다.
위에서 말했듯이 = 연산자와 () 활용한 대입은 같은 기능을 수행합니다.
그렇다면
sim2 = sim1 과
sim2(sim1) 은 같다고 볼 수 있습니다.
이렇게 보면 생성자에 호출문과 비슷하게 보입니다.
이제 Simple 클래스를 확인해 보겠습니다.
class Simple {
int a;
public:
Simple(int a) :a(a) {}
};
위처럼 SImple 클래스는 간단하게 선언되어 있습니다.
여기서 Simple 클래스에 생성자는 int 매개변수 하나만을 갖고 있습니다.
sim2(sim1) 이 생성자로서 호출이 되려면 위에 보이는 생성자로는 만족될 수 없습니다.
사실 Simple 클래스에 기본으로 생성이 되는 생성자가 숨어져 있습니다.
이것이 바로 디폴트 복사 생성자입니다.
class Simple {
int a;
public:
Simple(int a) :a(a) {}
Simple(Simple& copy) : a(copy.a) {}
};
위 코드는 디폴트 복사 생성자를 명시적으로 구현했을 때입니다.
복사 생성자를 정의하지 않으면, 멤버 대 멤버의 복사를 진행하는 디폴트 복사 생성자가 자동으로 삽입이 된다는 것을 알 수 있습니다.
마지막으로 하나 더 알아야 하는 점은
복사 생성자의 매개변수는 반드시 참조형이어야 한다는 점이다.
만약, & 선언이 없다면 복사 생성자의 호출은 무한루프에 빠지게 된다. 그 이유는 복사 생성자가 호출되는 시점과 관련이 있는데 이에 대해서는 좀 더 공부해 보고 정리하겠습니다.
'c++ > 복사 생성자' 카테고리의 다른 글
[C++] 복사 생성자의 호출 시점 (0) | 2023.01.04 |
---|---|
'깊은 복사'와 '얕은 복사' (2) | 2023.01.03 |