본문 바로가기
Programming/Effective C++ 3판

항목 11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자

by deviAk 2009. 2. 17.
반응형

내용
자기대입(self assignment) : 어떤 객체가 자기 자신에 대해 대입 연산자를 적용 하는 것을 말한다.

a[i] = a[j]; 또는 *px = *py; 는 자기대입의 가능성을 가지고 있는 문장이다. 어뜻 보기에 명확하지 않은 이러한 자기대입이 생기는 이유는 여러 곳에서 하나의 객체를 참조하는 상태, 즉 중복참조(aliasing)라고 불리는 것 때문이다.

그렇기 때문에, 같은 타입으로 만들어진 객체 여러개를 참조자 혹은 포인터로 물어 놓고 동작하는 코드를 작성할 떄는 같은 객체가 사용 될 가능성을 고려 하는것이 일반적으로 바람직한 자세이다.

해결법
  1. operator=의 첫머리에서 일치성 검사(identity test)를 통해 자기대입을 점검한다.
    자기대입의 경우 많이 일어나는 것이 아니기 때문에 모든 객체에 대해서 비교하는 것은 효율이 낮다.
  2. class CEx { ... };
    
    CTest& CTest::operator=(const CTest& rhs)
    {
     if ( this == &rhs) return *this; // 객체가 같은지, 즉 자기대입인지 검사한다.
                                      // 자기대입이면 아무것도 안한다.
    delete pMember;
    pMember = new CEx(*rhs.pMember);
    
    return *this;
    }
    
  3. 문장의 순서를 적절히 조정한다.
  4. class CEx { ... };
    
    CTest& CTest::operator=(const CTest& rhs)
    {
     CEx *pOrig = pMember;           // 원래의 pMember를 어딘가에 기억해 둔다.
     pMember = new CEx(*rhs.pMember);// 다음, pMember가 *pMember의 사본을 가르키게 만든다.
     delete pOrig;                   // 원래의 pMember를 삭제한다.
    
     return *this;
    }
    
  5. 복사 후 맞바꾸기(copy and swap) 기법을 사용한다.
  6. class CTest {
     ...
     void swap(CTest& rhs);   // *this의 데이터 및 rhs의 데이터를 맞바꾼다.
     ...
    };
    
    CTest& CTest::operator=(const CTest& rhs)
    {
     CTest temp(rhs);         // rhs의 데이터에 대한 사본을 하나 만든다.
    
     swap(temp);              // *this의 데이터를 그 사본의 것과 맞바꾼다.
     
    return *this;
    }
    



이것만은 잊지 말자!
- operator=을 구현할 때, 어떤 객체가 그 자신에 대입되는 경우를 제대로 처리하도록 만들자. 원본 객체와 복사대상 객체의 주소를 비교해도 되고, 문장의 순서를 적절히 조정할 수도 있으며, 복사 후 맞바꾸기 기법을 써도 된다.
- 두 개 이상의 객체에 대해 동작하는 함수가 있다면, 이 함수에 넘겨지는 객체들이 사실 같은 객체인 경우 정확하게 동작하는지 확인해 보자.


관련링크
http://ikpil.tistory.com/413
http://jangyeol.springnote.com/pages/348598.xhtml
http://evax.springnote.com/pages/871438
http://ilu8318.egloos.com/1705010
http://ikpil.tistory.com/299

반응형