복사생성자
복사생성자는 같은 클래스의 객체를 복사하여 객체를 만드는 생성자이다.
C++ 스타일의 초기화
우리는 지금까지 다음의 방식으로 변수를 초기화 했다.
int num = 20;
int &ref = num;
c++ 에서는 다음과 같은 방식으로 변수의 초기화가 가능하다.
int num(20);
int &ref(num);
두가지 초기화 방식은 결과적으로 동일하다.
기본 복사생성자
복사생성자를 명시적으로 선언하지 않으면 컴파일러는 객체의 멤버를 그대로 복사하여 객체를 생성하는 복사생성자를 자동으로 만든다.
#include <iostream>
using namespace std;
class Point {
int x;
int y;
public:
Point(int x = 0, int y = 0) : x(x), y(y) { }
Point& setX(int x) {
this->x = x;
return *this;
}
Point& setY(int y) {
this->y = y;
return *this;
}
void show() {
cout << "[" << x << "," << y << "]" << endl;
}
};
int main() {
Point p1(10, 50);
Point p2 = p1; // 복사
p1.setX(15).setY(35);
cout << "p1 : ";
p1.show();
cout << "p2 : ";
p2.show();
return 0;
}
위의 코드에서 Point p2 = p1
을 다음의 코드로 바꿔도 같은 결과가 된다.
기본 복사생성자는 다음과 같은 형태이다.
class ClassName {
(...)
public :
ClassName(const ClassName& copy)
: ( /* 초기화 리스트에서 모든 맴버 복사 */ )
{ }
(...)
}
위의 코드에 복사생성자를 만들어 보면 다음과 같이 된다.
Point(const Point& copy) // 복사생성자
: x(copy.x), y(copy.y)
{
cout << "복사생성자 호출" << endl;
}
깊은 복사와 얕은 복사
기본 복사생성자 처럼 모든 멤버를 각각 복사하는 방식을 얕은 복사라고 한다.
다음 코드에서 얕은 복사의 문제점이 무엇인지 확인해 보자.
기존에 만들었었던 Person 클래스를 활용합니다.
#ifndef __PERSON__
#define __PERSON__
class Person
{
char* name;
int age;
public:
Person(const char*, int);
Person();
~Person();
void showInfo() const;
void setInfo(char*, int);
};
#endif
#include <iostream>
#include "Person.h"
#include <cstring>
using namespace std;
Person::Person(const char* myname, int myage)
: age(myage)
{
int len = strlen(myname) + 1;
name = new char[len];
strcpy(name, myname);
}
Person::Person()
: age(0)
{
cout << "빈 객체 생성" << endl;
name = NULL;
}
Person::~Person()
{
cout << name << " 객체 소멸" << endl;
delete[] name;
}
void Person::showInfo() const {
cout << "이름 : " << name << endl;
cout << "나이 : " << age << endl;
}
void Person::setInfo(char* myname, int myage) {
name = myname;
age = myage;
}
#include <iostream>
#include "Person.h"
using namespace std;
int main() {
Person man1("ki yong", 43);
Person man2 = man1;
man1.showInfo();
man2.showInfo();
return 0;
}
객체 소멸시 동적할당된 객체를 삭제할때 문제가 발생됩니다.
깊은복사 생성자 정의
다음과 같이 복사생성자를 정의합니다.
Person.h에서 복사생성자를 선언합니다.
class Person {
(...)
public :
Person(const Person& copy); // 복사생성자 선언
(...)
};
Person.cpp에서 복사생성자를 정의합니다.
(...)
Person::Person(const Person& copy)
: age(copy.age)
{
int len = strlen(copy.name) + 1;
name = new char[len];
strcpy(name, copy.name);
}
(...)