operator=
라는 대입 연산자를 구현할 때, 객체가 자신에게 대입되는 경우에 대한 처리를 하도록 해야한다.
이러한 처리를 위해서 자기 자신과의 주소를 비교하거나 복사 후 바꾸는 방법을 사용하면 된다.
즉, 어떤 객체가 자기 자신에 대해 대입연산사를 사용하는 자기대입
을 조심해야 한다.
class Bitmap {
public:
Bitmap(int r, int g, int b) {
this->r = r;
this->g = g;
this->b = b;
}
private:
int r;
int g;
int b;
};
class Widget {
public:
Bitmap *bitmap;
Widget& operator= (const Widget& whs);
};
Widget& Widget::operator= (const Widget& whs) {
delete(bitmap);
this->bitmap = whs.bitmap;
}
위 코드의 문제점은 무엇일까?
위의코드는 문제가 생길 수 있는 코드이다.
만약 위의 코드 처럼 구현되어있는 코드에서 아래와 같이 호출이 된다면 문제가 되는 것이다.
Widget *temp;
void f(Widget widget) {
Widget r = *temp;
r = widget;
}
int main() {
Widget *widget = new Widget();
widget->bitmap = new Bitmap(1, 5, 3);
temp = widget;
f(*widget);
}
위와 같은 코드가 존재한다고 할 때, f라는 함수 내부에서 r과 widget은 같은 객체를 뜻하기 때문에 위의 operator=
이 불리게 된다.
따라서 Bitmap객체를 delete하고, 두 r과 widget 객체 모두 bitmap을 잃어버리게 되는것이다.
그렇기 때문에 operater을 구현 할 때에는 자기 대입에 대한 처리가 빠져선 안된다.
Widget& Widget::operator= (const Widget& whs) {//여기서 &는 참조(reference)
if(this == &whs) return *this;//여기서 &는 주소값
delete(bitmap);
this->bitmap = whs.bitmap;
}
위와 같이 같은 객체인지에 대한 예외처리를 통해 문제를 막을 수 있다.