소프트웨어/C/C++

c/c++] 연산자오버로딩(=이용)할때 주의(얕은복사,깊은복사)

cs만두 2013. 8. 11. 21:29

Person이라는 클래스가있다고 가정

Person은 char* name이라는 멤버변수를 갖고있음

 

 

 

Person a;

a.name= new char[strlen("kim")+1];

strcpy(a.name,"kim");

Person b;

b.name= new char[strlen("Lee")+1];

strcpy(b.name,"Lee");

 

 

이렇게 두개의 객체에 각각 name을 할당했다.

 

이때

a=b; 를 이용해서 대입을 했을시에 출력은 되지만 오류창이 뜬다.

 

이유는 대입연산자에 있다.

 

a=b를 쓰면

사용자가 따로 정의하지 않는이상 디폴트 대입연산자가 불리는데

Person& Person::operator=(const Person& p){

name=p.name; //포인터대입

return *this;

}

형태이다.

이때 문제가되는게 p.name자체도 문자열을 가리키는 포인터라서, 새로 대입되는 피연산자의 name도 p.name과 같은 문자열을 가리키게 된다.

여기까지는 문제가 없다. 그래서 출력을 해보면 내가 원하는대로 Lee,Lee가 인쇄된다.

그다음 문제가 생기는데, 함수가 리턴되면서 deconstructor가 수행될때 b를 먼저 삭제(free)하는데(왜냐하면 a,b순으로 입력하였으므로 밖에놈부터 먼저 삭제), 그 후 a를 삭제하면서 a.name이 가리키는 문자열에 delete[]를 시도하면서 오류가 생긴다. 이미 b단계에서 삭제가 완료되었기 때문이다.

앞에서 디폴트대입연산자가 수행한 복사방식을 얕은복사shallowcopy라고 한다.

 

이것을 해결하기위해 디폴트 대입연산자대신 새로운 대입연산자를 정의하면된다.

Person& Person::operator=(const Person& p){

delete[] name; //이전 name값이 미아가 된다. 그래서 메모리유출을 방지하기위해 name자체를 free시킨다.

name= new char[strlen(p.name)+1]; //새로 name에 메모리를 할당하고

strcpy(name, p.name); // 문자열 자체를 새로 넣어준다.

return *this;

}

위와같은 방법을 깊은복사deep copy라고 한다.