Chapter 2. 생성자, 소멸자 및 대입 연산자 part2 항목 10 - 12

Effecive C++ 정리

Posted by Kyung Jun Cha on 2019-10-31

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; //rhs와 this가 같은 객체인 경우 문제 발생
pb = new Bitmap(*rhs.pb);

return *this;
}

해결책

  1. 일치성 검사
1
2
3
4
5
Widget& Widget::operator=(const Widget& rhs)
{
if(this == &rhs) return *this; // 코드 실행전 일치성 검사
...
}
  1. 실행 순서 조정
1
2
3
4
5
6
7
8
Widget& Widget::operator=(const Widget& rhs)
{
Bitmap *pOrig = pb; //원래의 pb를 기억해 둡니다.
pb = new Bitmap(*rhs.pb);
delete pOrig;

return *this;
}
  1. 복사 후 맞바꾸기(copy and swap)
1
2
3
4
5
6
7
Widget& Widget::operator=(const Widget& rhs)
{
Widget temp(rhs);
swap(temp); // *this의 데이터를 그 사본의 것과 맞바꿉니다.

return *this;
}

두 개 이상의 객체에 대해 동작하는 함수가 있다면, 이함수에 넘겨지는 객체들이 사실 같은 객체인 경우에 정확하게 동작하는지 확인해 보시오

항목 12: 객체의 모든 부분을 빠짐없이 복사하자

  1. 해당 클래스의 데이터 멤버를 모두 복사해야 합니다.
  2. 이 클래스가 상속한 기본 클래스의 복사 함수도 꼬박꼬박 호출해 주도록 합니다.
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;
}