OSgood의 개발일기

대입 연산자(Shallow copy VS Deep copy) 본문

C++/문법

대입 연산자(Shallow copy VS Deep copy)

OSgood 2019. 5. 7. 18:26

 Class의 디폴트 대입 연산자는 멤버 간의 Shallow copy로 되어 있다. 이 때 클래스의 멤버들이 동적할당을 이용하고 있지 않으면 큰 문제가 발생하지 않는다. 하지만 만약 복사하는 값이 주소값이라면 Shallow copy는 큰 문제를 야기하고 런타임 에러를 발생시킬 수도 있다. 

 왜냐하면 동적할당으로 얻은 메모리를 이용할 때 Shallow copy를 하게 되면 메모리 공간은 그대로이고 이것을 가르키는 포인터는 양쪽 객체에서 똑같이 가지고 있기 때문에 한 쪽 객체의 destructor에서 메모리를 해제할 경우 다른 쪽에서의 접근은 실뢰할 수 없는 메모리 공간이 된다.

========================================================================

 그림을 보면 이해가 더 쉬울 것 같아서 간단히 그림을 만들어 보았다. 위와 같이 Shallow copy를 하게 되면 한쪽은 소멸시켰을 때 문제가 발생한다. 반면 Deep copy를 진행할 경우 위 그림에서 두 개의 "osgood"을 각각 만들어 참조하고 있기 때문에 각각 소멸시킬 때에도 문제가 안 된다.

 

 아래의 코드를 통해 실습을 해보면 더 이해가 잘 될 것 같다. 지금은 deep copy를 기준으로 대입연산자가 만들어져 있다. 만약 shallow copy의 문제점을 확인하고 싶다면 아래에서 operator=를 삭제하고 디폴트 operator로 테스트를 진행하면 될 것 같다.

#include "pch.h"
#include <iostream>
#include <cstring>

using namespace std;

class Test
{
private:
	char *name;
	int cups;

public:



	Test(char *InputName, int MyCup);
	~Test();
	void Show();
	Test& operator=(const Test& ref);//shallow copy를 하려면 주석처리!


};

Test::Test(char *InputName, int MyCup)
{
	int len = strlen(InputName) + 1;
	name = new char[len];
	strcpy(name, InputName);
	cups = MyCup;

}
void Test::Show()
{
	cout << "이름:	" << name << endl;
	cout << "가지고 있는 컵 갯수:	" << cups << endl;

}
Test::~Test()
{
	delete[]name;
	cout << "Destructor is Called" << endl;
}
Test& Test::operator=(const Test& ref)
{//shallow copy를 하려면 주석처리!
	delete[]name;
	int len = strlen(ref.name) + 1;
	name = new char[len];
	strcpy(name, ref.name);
	cups = ref.cups;
	return *this;

}
void main()
{
	Test person1((char*)"osgood", 2);
	Test person2((char*)"LCJ", 4);
	person1.Show();
	person2.Show();
	person2 = person1;
	cout << "#####################		Shallow copy VS Deep copy test #####################" << endl;
	cout << "#####################		If you using deep copy operator as above, compile error is occured!! #####################" << endl;
	person1.Show();
	person2.Show();
}


 

 

 

'C++ > 문법' 카테고리의 다른 글

참조자(reference) VS 포인터(pointer)  (0) 2019.05.08
오버로딩(Overloading) VS 오버라이딩(Overriding)  (0) 2019.05.07
[C++] 연산자 오버로딩  (0) 2019.03.21
[C++] Class정리  (0) 2019.03.21
[c++] static  (0) 2019.03.14
Comments