[C++] 복사 생성자(Copy constructor), 얕은 복사(Shallow Copy), 깊은 복사(Deep Copy)

2022. 2. 9. 00:45Languages/C++

*<씹어먹는 C++>을 보며 공부하여 정리한 글입니다.

 

 

 

1. 복사 생성자(Copy constructor)

 

  • 객체를 복사하여 생성할 때 호출되는 생성자를 말한다.
  • 사용자가 따로 넣지 않을 경우, 컴파일러가 자동적으로 디폴트 복사 생성자를 삽입해준다.
class Monster {
    char* name;
    int hp;
    int damage;

public:
	Monster(const Monster& copyMonster);    // 복사 생성자
    ...
};

 

  • 함수 내부에서, 받은 인자의 값을 변경할 일이 없다면 다음과 같이 정의하는 것이 더 안전하다.
Moster(const Monster& copyMonster);

 

  • 즉, 다른 객체의 상수 레퍼런스를 매개변수로 받는다.
    • const 이기 때문에 복사 생성자 내부에서 매개변수로 가져온 참조 데이터를 직접 변경하는 것이 불가능하다.
    • 즉, 읽어와서 복사하는 것만 가능하기에 실수로 참조 데이터 값을 변경한다는 등의 실수를 줄일 수 있다.
  • 복사 생성자는 오직 객체 생성 시에만 호출된다.
Monster monster1;
Monster monster2(monster1);     // 복사 생성자 호출
Monster monster3 = monster1;    // 역시 복사 생성자 호출


Monster monster4;
monster4 = monster1;            // 단순 대입 연산. 복사 생성자 호출 X

 

 

얕은 복사(Shallow Copy)

 

  • 값들을 복사하여 새로 생성한 객체에 대입해주는 연산을 의미한다.
  • 디폴트 복사 생성자얕은 복사 과정을 진행한다.
  • 포인터참조한 값을 복사하여 대입하면, 소멸자가 실행될 때 중복 delete가 될 수 있기에 문제가 발생한다.
Monster(const Monster& copyMonster) {
   hp = copyMonster.hp;
   damage = copyMonster.damage;
   // name = copyMonster.name;      같은 name을 가리키기 때문에 중복 delete의 위험이 있다.
}

 

 

깊은 복사(Deep Copy)

 

  • 얕은 복사를 진행하되, 포인터나 참조한 값은 새로 메모리를 할당하여 복사해주는 것을 말한다.
  • 이렇게 할 시, 소멸자에서 각각 다른 메모리를 해제하기 때문에 문제가 발생하지 않는다.
  • 위에도 언급했듯이, 디폴트 복사 생성자는 얕은 복사만 하므로 깊은 복사를 하는 생성자는 직접 만들어줘야 한다.
Monster(const Monster& copyMonster) {
   hp = copyMonster.hp;
   damage = copyMonster.damage;
   
   // 깊은 복사. C-style보다는 string을 추천하지만 예시를 들기 위해...
   name = new char[strlen(copyMonster.name) + 1];
   strcpy(name, copyMonster.name);
}

 

 

728x90
반응형