복사생성자와 얕은복사
- 프로그래밍/C++
- 2011. 3. 20. 22:59
깊은복사와 얕은복사의 정리
2011/03/09 - [프로그래밍/C언어] - 얕은 복사,깊은 복사
보통 디폴트복사생성자가 작동하는 방식이 얕은복사다 . (1:1 대응으로 인한 값 복사)
일반 경우에는 이러한 얕은복사를 사용해도 문제가 생기지 않지만 복사하는 값이 주소일 경우에는 문제가 생긴다.
동적할당으로 얻은 메모리를 이용할 때 얕은복사를 하면 메모리 공간은 그대로지만 그것을 가리키는 포인터는 양쪽 객체에서 똑같이 갖고 있기 때문에 어느 한 쪽에서 객체가 메모리를 해제하면 다른 쪽에서의 접근은 신뢰할 수 없는 메모리 공간이 된다.
이러한 경우를 해결하기 위해서 생긴게 깊은복사 인데,
동적 할당된 메모리를 포인터만 복사해서 생기는 얕은복사의 문제점을 해결할 수 있는게 깊은복사인데 깊은복사란 메모리 속의 내용까지 완전히 복사를 수행하는 것 이다. 복사 생성자에서도 동적 할당으로 메모리를 얻어서 값을 대입 해 담는다. 양 쪽의 서로다른 객체가 각각의 다른 동적메모리에 같은 값을 같게 된다.
얕은복사 |
|
class Test { int * m_px; int m_ny; public: Test(int _x, int _y) { this->m_px = new int; *(this->m_px) = _x; this->m_ny = _y; } ~Test() { delete m_px; } };
void main() { Test test1 = Test(10,20); Test test2 = Test(test1); } |
Test(Test & test) { this->m_px = test.m_px; this->m_ny = test.m_ny; } 왼쪽 코드를 살펴보면 위와 같은 복사생성자가 생성된다. 하지만 delete가 동적 할당된 메모리를 해제하다가 실패하게 되는데 this->m_px = test.m_px; // 포인터 대입 this->m_ny = test.m_ny; // 값 대입 다음과 같은 코드에서 this->x = test.x; 는 동적 할당된 영역을 가르키기는 포인터이기 때문에 한쪽 객체에 할당한 메모리의 포인터가 다른 객체에도 복사되기 때문이다. 동적 할당된 메모리 상의 공간은 하나 뿐인데 이 공간에 대한 포인터는 각각의 객체가 복사해서 가지고 있다. 첫번째 객체가 소멸되면서 할당된 값은 delete되지만 두번째 객체가 소멸되면서 기존에 소멸시켰던 포인터를 다시 해제하려고 하기 때문에 오류가 난다. |
깊은복사 |
|
class Test { int * m_px; int m_ny; public: Test(int _x, int _y) { this->m_px = new int; *(this->m_px) = _x; this->m_ny = _y; } Test(const Test* test) { this->m_px = new int; //동적할당 *(this->m_px) = *test.m_px;
this->m_ny = test.m_ny; } ~Test() { delete m_px; } };
void main() { Test test1 = Test(10,20); Test test2 = Test(test1); } |
다음과 같이 복사생성자를 설정해줌으로써 각각의 객체는 서로 다른 주소를 할당받게 된다.
[출처] 얕은복사 vs 깊은복사|작성자 편애 |
결론은 디폴트 복사생성자는 얕은복사하니
포인터를 가지고있는 클래스는 모두 복사생성자를 만들어서 깊은복사를 해줘여함(무조건하는 습관을 들이자 ㅎㅎ)
출저: http://blog.naver.com/kyung778?Redirect=Log&logNo=60121742619
추가한부분
복사생성자가 제대로 안만들어질경우
메모리 해제할때 힙메모리 어쩌구저쩌구 에러뜬다!! ㅎㅎㅎㅎ
이 글을 공유하기