복사생성자와 얕은복사


깊은복사와 얕은복사의 정리
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




추가한부분
복사생성자가 제대로 안만들어질경우
메모리 해제할때 힙메모리 어쩌구저쩌구 에러뜬다!! ㅎㅎㅎㅎ



이 글을 공유하기

댓글

Designed by JB FACTORY