당신의 값 부여 조작부호는 대상을 대상 자체에 정확하게 부여할 수 있습니까?

14457 단어
C++ operator = 자기 할당을 판단하는 이유
Operator=함수 구현을 쓸 때 주의해야 할 문제는 다음과 같다. 고객이 다음 코드를 완전히 쓸 수 있기 때문이다. 대상이 스스로 값을 부여하는 상황을 고려해야 한다.

       
       
       
       
  1. Widget w;
  2. ...
  3. w=w;

이렇게 쓰는 것은 완전히 합법적이다. 그러면 우리는Widget:operator=(xx)의 실현을 쓸 때 반드시 이 문제를 고려해야 한다. 그렇지 않으면 상상할 수 없는 문제들이 너를 찾아온다. 허허, 예를 들어 지금 Widget가 하나 있다.

       
       
       
       
  1. class Bitmap{};
  2. class Widget{
  3. public:
  4. ...
  5. Widget& operator=(const Widget& rhs){
  6. delete hBitmap_;//hBitmap_ NULL, :delete NULL , .
  7. hBitmap_ = new Bitmap(*rhs.hBitmap_);
  8. return *this;
  9. }
  10. private:
  11. Bitmap* hBitmap_;
  12. };

이곳의 rhs와 *this가 같은 대상이라면 어떤 문제가 발생합니까?그러니까 두 대상의 hBitmap.같은 그림 데이터입니다. delete hBitmap실행될 때, 그들이 가리키는 동일한 비트맵 자원이 방출되고, 이어서 다음 문장을 실행하면 문제가 발생한다. 왜냐하면 새로 발생한 hBitmap무효 대상입니다.프로그램이 계속 아래로 내려갈 때 메모리에 접근하는 등의 문제가 발생할 수 있다.이때 당신은 이 문제를 알아차리고 코드를 수정하기 시작했다.

       
       
       
       
  1. Widget& Widget::operator=(const Widget& rhs){
  2. if(this == &rhs){ //
  3. return *this;
  4. }
  5. delete hBitmap_;
  6. hBitmap_ = new Bitmap(*rhs.hBitmap_); // throw possibel exception?
  7. return *this;
  8. }

코드는 논리적 판단문을 추가하여'자기부치 안전'문제를 해결하였으나 new Bitmap(*rhs.hBitmap)일 경우이 문장에 이상이 생기면 hBitmap바로 예측할 수 없는 값이다. 이렇게 하면 매우 무서워서'이상성 안전'문제의 출현을 초래한다.왕왕 Operator='이상 안전성'을 얻었지만 자동으로'자기부치 안전'의 보답을 받기 때문에 많은 사람들이'이상 안전성'에 초점을 맞추고'자기부치 안전성'에 대해 내버려두기 때문에 그들은 이런 방안을 생각해냈다. 즉, 값을 부여하기 전에 이전의 대상을 삭제하지 않는 것이다.이렇게 하면 다음과 같은 코드를 쓸 수 있다.

       
       
       
       
  1. Widget& Widget::operator=(const Widget& rhs){
  2. Bitmap* holdBitmap_ = hBitmap_;
  3. hBitmap_ = new Bitmap(*rhs.hBitmap_);
  4. delete holdBitmap_;
  5. return *this;
  6. }

이렇게 하면 "new Bitmap(*rhs.hBitmap)"이상을 던지면 좌우 조작 대상이 변하지 않고'이상 안전성'을 유지하며'자기부치 안전성'을 유지한다. 이것은 통할 수 있다. 그러나 효율 문제를 고려하면'이상 안전성'을 중시하는 대체 방안이 더 좋은 선택이 될 것이다. 이것은'copy and swap'을 통해 실현된 것이다(조항29는 더욱 상세한 연구를 할 것이다).

       
       
       
       
  1. class Widget{
  2. public:
  3. Widget& operator=(const Widget& rhs){
  4. Widget tempt(rhs); //make a source copy
  5. swap(rhs);
  6. return *this;
  7. }
  8. ...
  9. private:
  10. void swap(const Widget& rhs); // Widget
  11. ...
  12. };

매개 변수의 복사본을 생성할 수 있기 때문에 "pass byvalue"를 통해 매개 변수를 전달할 수 있습니다. 코드를 다시 고칩니다.

       
       
       
       
  1. class Widget{
  2. public:
  3. Widget& operator=(Wiget rhs){
  4. swap(rhs);
  5. return *this;
  6. }
  7. ....
  8. private:
  9. void swap(const Widget& rhs); // Widget
  10. ...
  11. };

이러한 함수 서명은 보기에 그리 편하지 않지만, 교묘하게 코드를 수정하기 위해 코드의 가독성을 희생했지만, '코피잉 동작' 을 함수 본체에서 '함수 매개 변수 구조 단계' 로 옮기면 컴파일러가 때때로 더 높은 효과 코드를 생성할 수 있다.기억해 두세요:◆대상이 스스로 값을 매길 때operator=좋은 행동을 하도록 하세요.그 중에서 기술은'출처 대상'과'목표 대상'의 주소 비교, 세심한 문장 순서,copy-and-swap.◆ 어떤 함수든 한 개 이상의 대상을 조작하고 그 중 여러 개의 대상이 같은 대상일 때 그 행위는 여전히 정확하다.

좋은 웹페이지 즐겨찾기