본문 바로가기

C++/C++ 문법

[C++] 얕은 복사, 깊은 복사

728x90
반응형

얕은 복사

 

디폴트 복사 생성자는 멤버 대 멤버의 복사를 진행한다.

 

이때 일어나는 복사 방식을 얕은 복사라고 한다.

 

이를 좀 더 자세히 설명하기 위해 아래 코드를 사용해 보겠다.

 

#include <iostream>
#include <cstring>
using namespace std;

class student {
private:
	char* name;
	int age;
public:
	student(const char* myname, int myage)
	{
		int len = strlen(myname) + 1;
		name = new char[len];
		strcpy_s(name, len, myname);
		age = myage;
	}
	~student()
	{
		delete []name;
		cout << "called destructor!" << endl;
	}

};

int main() {
	student person1("Enchupin", 20);
	student person2 = person1;

	return 0;
}

 

 

위 코드에서 person1을 생성한 후 인자를 전달하는 과정까지는 문제가 없다.

 

그러나 person2 객체를 생성하고 멤버 대 멤버 복사를 진행하는 과정에서 person2.nameperson1.name을 복사한다.

 

그런데 이때 값을 복사하여 person2.name에 넣는 것이 아니라 주소를 복사하여 사용하는 방식으로 복사가 진행된다.

 

이때 일어날 수 있는 문제점은 person1.nameperson2.name이 같은 곳을 가리키고 있기 때문에

어느 한쪽의 객체의 소멸자가 호출되어 delete []name;이 실행되면 두 객체 모두 name을 사용할 수 없게 되는 것이다.

 

따라서 위 코드에서 "called destructor!"는 한 번만 출력되는 것을 확인할 수 있다.

*C++ 표준을 엄격히 지키는 visual studio에서는 컴파일 자체를 허용하고 있지 않다.

 

 

 

 

 

깊은 복사

 

따라서 이러한 문제를 해결하기 위해 깊은 복사를 사용해야 한다.

 

깊은 복사를 사용한다는 의미는 문자열의 주소값을 복사하는 것이 아닌 개별적인 값을 복사해야 한다는 의미이다.

 

따라서 아래 코드와 같은 복사생성자를 선언해 줌으로써 해결할 수 있다.

 

	student(const student& copy)
		:age(copy.age)
	{
		name = new char[strlen(copy.name) + 1];
		strcpy_s(name, strlen(copy.name)+1, copy.name);
	}

 

위 코드에서는 name을 동적으로 할당한 후 값을 복사하고 있으므로 name을 동적으로 할당한 시점에서

인자로 입력받는 객체의 name과는 다른 주소값을 가리키고 있다.

 

 

 

 

 

 

 

728x90
반응형