C++/C++

Effective C++ Operator = 에서는 자기 대입에 대한 처리가 빠지지 않도록 하라

Elan 2021. 6. 27. 00:57

Do not take away the processing of self-admission in Operator=

 

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){
   delete(bitmap);
   this->bitmap = whs.bitmap;
   }
};


만약 위의 코드를 아래와 같이 호출한다면 문제가 발생한다.

Widget *temp;

void func(Widget widget) {
   Widget r = *temp;
   r = widget;
}

int main() {
   Widget *widget = new Widget();
   widget->bitmap = new Bitmap(1, 5, 3);
   temp = widget;
   func(*widget); // 에러
}

func라는 함수 내부에서 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;
}

 같은 객체인지에 대한 예외처리를 통해 문제 발생을 차단 하자.