Chapter 2. 생성자, 소멸자 및 대입 연사자
항목 10. 대입 연산자는 *this
의 참조자를 반환하게 하자
1 2 3
| int x, y, z; x = y = z = 15; x = (y = ( z = 15));
|
위의 예에서 보이듯이 대입 연산은 우측 연관 연산이므로 *this
를 반환함으로서 연산이 사슬처럼 엮일 수 있다.
항목 11. operator=
에서는 자기대입에 대한 처리가 빠지지 않도록 하자.
Ex) 자기 참조 가능성이 있는 위험한 코드
1 2 3 4 5 6 7 8 9 10 11 12 13
| class Widget { ... private: Bitmap* pb; };
Widget& Widget::operator=(const Widget& rhs) { delete pb; pb = new Bitmap(*rhs.pb);
return *this; }
|
해결책
- 일치성 검사
1 2 3 4 5
| Widget& Widget::operator=(const Widget& rhs) { if(this == &rhs) return *this; ... }
|
- 실행 순서 조정
1 2 3 4 5 6 7 8
| Widget& Widget::operator=(const Widget& rhs) { Bitmap *pOrig = pb; pb = new Bitmap(*rhs.pb); delete pOrig;
return *this; }
|
- 복사 후 맞바꾸기(copy and swap)
1 2 3 4 5 6 7
| Widget& Widget::operator=(const Widget& rhs) { Widget temp(rhs); swap(temp);
return *this; }
|
두 개 이상의 객체에 대해 동작하는 함수가 있다면, 이함수에 넘겨지는 객체들이 사실 같은 객체인 경우에 정확하게 동작하는지 확인해 보시오
항목 12: 객체의 모든 부분을 빠짐없이 복사하자
- 해당 클래스의 데이터 멤버를 모두 복사해야 합니다.
- 이 클래스가 상속한 기본 클래스의 복사 함수도 꼬박꼬박 호출해 주도록 합니다.
1 2 3 4 5 6 7 8 9 10 11
| Derived::Derived(const Derived& rhs) : Base(rhs) { ... }
Derived& Derived::operator=(const Derived& rhs) { Base::operator=(rhs); ... return *this; }
|