개발/C++

[C++] 복사 생성자

hojak99 2016. 10. 3. 19:21

C++에는 복사 생성자라는 것이 있다이 복사 생성자는 어떤 객체의 초기화를 위해 그와 같은 타입의 객체로부터 초기화할 때 호출되는 함수인데 나는 이 복사 생성자가 헷갈리고 실수를 많이 할 수 있을 부분이라 중요하다고 생각한다.



[복사 생성자]


class ABC {

private:

int a;

int b;

public:

ABC(int _a, int _b) : a(_a), b(_b) {}

};


void main

{

ABC abc(5, 10);

ABC abc2(abc);


//abc2 a, b를 출력하면 5, 10 이 정상적으로 출력이 된다.

 

//ABC abc = ABC(5, 10);

//ABC abc2 = abc;

};



이 코드를 보면 뭐가 문제지라는 생각을 할 수도 있다하지만 여기서 중요한 것은 바로 ‘ABC abc2(abc)’ 바로 이 코드이다이 코드에 대해서 설명하기 전 알아두어야 할 것이 있는데 ‘ABC abc2 = abc’ 코드는 묵시적으로 변환되어 바로 ‘ABC 


abc2(abc)’ 이렇게 객체가 생성된다고 한다그렇다면 이제 여기서 생각해 보아야 할 문제를 보자그것은 ‘ABC abc2(abc)’에서 ABC 객체를 인자로 받는 생성자가 위의 코드 상에서는 보이지 않는다그런데 컴파일이 되면서 abc2 객체의 멤버 변수에 값이 abc 객체의 멤버 변수 값으로 바뀌었다바로 이것이 복사 생성자 라는 것 때문이다.


이렇게 복사 생성자를 선언하지 않아도 복사가 되는 이유는 디폴트 복사 생성자가 있기 때문이다컴파일러에서 자동으로 만들어 주는 디폴트 복사 생성자는 문제가 있다디폴트 복사 생성자의 문제를 알아보기 전 알아가야 할 것이 있다!


1. 얕은 복사

           - 값만 복사하는 형태이다.

포인터 등을 복사 시 같은 주소를 참조하기 때문에값 변경동적 해제 등에서 문제가 발생한다.

2. 깊은 복사

           - 주소가 가르키는 값그 메모리의 값을 복사

포인터 등을 복사 시 같은 주소를 참조하지 않고 새로운 주소를 할당 받고 새로 참조하기 때문에 값 변경동적 해제 등에서 문제가 발생하지 않는다!

 

이 두가지 복사 중 디폴트 복사 생성자는 어떤 복사일까바로 디폴트 복사 생성자는 얕은 복사이다그래서 아까 말했던 디폴트 복사 생성자의 문제점은 바로 포인터 등을 복사할 때 같은 주소를 참조(EX- 객체 A를 B로 복사했을 때 A와 B의 주소가 같은 주소를 참조)하게 되므로 동적 할당값을 변경할 때 오류가 발생하게 된다.

그렇다면 우리는 깊은 복사를 시켜주는 복사 생성자를 만들어야 한다.



[깊은 복사]


class ABC {

private:

char *a;

int b;


public:

ABC(char* _a, int _b){

  b = _b;

  a = new char[strlen(_a)+1];

  strcpy(a, _a);

}


ABC(const ABC &A){

  b=A.b;

  a = new char[strlen(A.a)+1];

  strcpy(a, A.a);

}


void main()

{

  ABC a(“KJH”, 18);

ABC b(a);

  //클래스 b의 멤버 변수를 출력하면 KJH, 18이 출력된다이것이 바로 깊은 복사이다.

}


 

2. 복사 대입 연산자는 뭐지?

복사 생성자는 이제 알겠는데 복사 대입 연산자는 무엇일까?

이것의 정의는 쉽다.

복사 대입 연산자는 같은 타입의 다른 객체에 어떤 객체의 값을 복사하는 용도로 쓰이는 함수이다복사 생성자는 초기화를 위한 것이고복사 대입 연산자는 값을 복사하기 위한 용도로 쓰이는 함수라고 생각하면 된다.

 

반응형