반응형
내용
자기대입(self assignment) : 어떤 객체가 자기 자신에 대해 대입 연산자를 적용 하는 것을 말한다.
a[i] = a[j]; 또는 *px = *py; 는 자기대입의 가능성을 가지고 있는 문장이다. 어뜻 보기에 명확하지 않은 이러한 자기대입이 생기는 이유는 여러 곳에서 하나의 객체를 참조하는 상태, 즉 중복참조(aliasing)라고 불리는 것 때문이다.
그렇기 때문에, 같은 타입으로 만들어진 객체 여러개를 참조자 혹은 포인터로 물어 놓고 동작하는 코드를 작성할 떄는 같은 객체가 사용 될 가능성을 고려 하는것이 일반적으로 바람직한 자세이다.
해결법
- operator=의 첫머리에서 일치성 검사(identity test)를 통해 자기대입을 점검한다.
자기대입의 경우 많이 일어나는 것이 아니기 때문에 모든 객체에 대해서 비교하는 것은 효율이 낮다.
- 문장의 순서를 적절히 조정한다.
- 복사 후 맞바꾸기(copy and swap) 기법을 사용한다.
class CEx { ... }; CTest& CTest::operator=(const CTest& rhs) { if ( this == &rhs) return *this; // 객체가 같은지, 즉 자기대입인지 검사한다. // 자기대입이면 아무것도 안한다. delete pMember; pMember = new CEx(*rhs.pMember); return *this; }
class CEx { ... }; CTest& CTest::operator=(const CTest& rhs) { CEx *pOrig = pMember; // 원래의 pMember를 어딘가에 기억해 둔다. pMember = new CEx(*rhs.pMember);// 다음, pMember가 *pMember의 사본을 가르키게 만든다. delete pOrig; // 원래의 pMember를 삭제한다. return *this; }
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
반응형