Software Development/C, C++

[C++] 복사 생성자(Copy Constructor)

huiyu 2018. 12. 18. 17:53

- C++ 스타일 초기화

  int num = 20;
  int &ref = num;

or

  int num(20);
  int &ref(num);

-> C++에서는 위의 두가지 초기화 방식을 동시에 지원한다.


*객체에서는?

  -> 객체에서도 변수의 초기화와 같이 대입, 괄호 두가지 초기화 방식을 모두 지원한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class SoSimple
{
private:
  int num1;
  int num2;
 
public:
  SoSimple(int n1, int n2) : num1(n1), num2(n2)
  {}
  void ShowSimpleData()
  {
    cout<<num1<<endl;
    cout<<num2<<endl;
  }
};
 
int main(void)
{
  SoSimple sim1(1520);
  SoSimple sim2 = sim1;
  sim2.ShowSimpleData();
  return 0;
}
cs

 출력 결과 15와 20이 출력된다.

 * SoSimple sim2 = sim1

 -> sim2객체가 생성된 다음, sim2객체로 sim1의 멤버변수의 복사가 일어난다.

 SoSimple sim2 = sim1은 실은 SoSimple sim2(sim1)의 형태로 묵시적 변환이 되어서(자동으로 변환이 되어서) 객체가 생성되는 것이다.

  SoSimple sim2(sim1);<-이 문장에 담겨있는 내용을 정리하면,
   1) SoSimple형 객체를 생성
   2) 생성한 객체의 이름은 sim2로 지정
   3) sim1을 인자로 받을 수 있는 생성자의 호출을 통해 객체생성을 완료 

3)을 호출하기 위한 SoSimple을 인자로 받는 생성자는 아래의 형태이다.

1
2
3
4
SoSimple(const SoSimple &copy) : num1(copy.num1), num2(copy.num2)
{
  ....
}
cs

 ** 이러한 생성자를 가리켜 '복사 생성자(Copy constructor)'라 부른다.
  키워드 const를 삽입해서 복사에 사용되는 원본의 변경을 막는다.

**위의 예제에선 선언하지 않은 함수인데?
 
-> 복사생성자를 정의하지 않으면, 멤버 대 멤버의 복사를 진행하는 '디폴트 복사 생성자'가 자동으로 삽입된다.


 - explicit 키워드

   위 예제에서

   SoSimple sim2 = sim1;

   의 코드는

   SoSimple sim2(sim1)

  의 형태로 묵시적 변환이 일어나 복사 생성자가 호출된다고 하였다.

  이는 결국, 복사 생성자가 묵시적으로 호출된 것으로 볼 수 있다.
  이러한 묵시적 호출을 막기 위해서 사용 하는 키워드가 explicit 키워드이다.

1
2
3
4
explicit SoSimple(const SoSimple &copy) : num1(copy.num1), num2(copy.num2)
{
  ....
}
cs

 -> 위와 같이 선언하면 대입연산자를 이용한 객체의 생성 및 초기화가 불가능하다.


*이러한 묵시적 변환은 복사생성자에서만 일어나는게 아니다.

1
2
3
4
5
6
7
8
9
class AAA
{
private:
  int num;
public:
  AAA(int n) : num(n) { }
  .....
};
 
cs

위와같은 클래스가 있을 경우, 아래와 같이 객체 생성이 가능하다.

 AAA obj = 3; // AAA obj(3);으로 변환

 그러나 생성자에 explicit가 선언되었다면, 위의 형태로 초기화가 불가능하다.


[참고자료]
윤성우 열혈 C++ 프로그래밍 05-1 '복사 생성자'와의 첫만남

728x90