2011-04-14 2 views
4

"Effective C++"에서이 내용을 읽었습니다. Col.10입니다. 할당 연산자가 * this에 대한 참조를 반환하도록하는 것이 좋습니다. 이 아이디어를 테스트하기 위해 코드 스 니펫을 작성했습니다. 대위 연산자를 무시했습니다. 그리고 시험해 봤습니다. 모든 것이 좋습니다. 하지만 해당 연산자를 제거하면 모든 것이 동일합니다. 즉, 체인 할당은 여전히 ​​잘 작동합니다. 그래서 나는 무엇을 놓치고 있습니까? 왜 그런가요? 너희들 한테 몇 가지 설명이 필요해, 고마워. 당신이 완전히 operator= 방법을 제거하면할당 연산자가 C++에서 * this에 대한 참조를 반환합니다.

#include <iostream> 

using namespace std; 

class Widget{ 
public: 

    Widget& operator=(int rhs) 
    { 
     return *this; 
    } 
    int value; 

}; 

int main() 
{ 
    Widget mywidget; 
    mywidget.value = 1; 
    Widget mywidget2; 
    mywidget2.value = 2; 
    Widget mywidget3 ; 
    mywidget3.value = 3; 
    mywidget = mywidget2 = mywidget3; 
    cout << mywidget.value<<endl; 
    cout << mywidget2.value<<endl; 
    cout << mywidget3.value<<endl; 

} 

답변

6

은 기본 operator=은 얕은 복사를 1를 구현하고 *this에 대한 참조를 반환 컴파일러에 의해 생성됩니다. 덧붙여

, 당신이 당신의 오버로드 된 연산자 오른쪽에 int의 작동하도록 설계되어 있기 때문에 실제로이 기본 operator=를 호출하고

mywidget = mywidget2 = mywidget3; 

물품.

예를 들어, 값이 const 인 경우 (예 : 컴파일 오류가 발생 함) 또는 *this과 다른 내용의 참조를 반환하면 연결 할당이 작동을 멈 춥니 다. 우연히 있다).

부분적으로 관련 : copy and swap idiom, 즉 할당 연산자를 작성하는 완벽한 방법입니다. 당신이 작성해야 할 경우 강력하게 읽어 충고 operator=


  1. 왼쪽 피연산자의 각 구성원과 오른손 하나의 각 구성원 사이의 할당이있는 것처럼 operator=가 수행 할 기본. 즉, 원시 타입의 경우 "잔인한"비트 카피가됩니다.이 경우 90 %의 경우 소유 자원에 대한 포인터가 좋지 않습니다. 예를 들어, -
+0

오, 알겠습니다. 그렇다면 항상 코드에서이 작업을 수행해야합니까? 아니면 컴파일러에서 처리하도록 하시겠습니까? –

+3

클래스가 필요하다면, 즉 기본 비트 복사가 괜찮 으면'operator ='를 구현해야합니다. 이는 일반적으로 클래스가 소유 한 리소스에 대한 메모리/핸들에 대한 원시 포인터가있을 때 발생합니다. 엄지 손가락의 좋은 법칙은 소멸자가 자원을 확보해야하는 경우, 다른 인스턴스, 이중 해제 및 자원 유출 사이에서 이러한 자원의 원하지 않는 공유를 피하기 위해'operator ='가 필요할 것입니다. –

+2

비트 단위 복사가 아닌 ... '연산자 ='가없는 멤버의 경우 비트 단위 복사를 수행하지만이를 구현하는 멤버의 경우 ('std :: string'을 생각해보십시오.) 기존의 연산자 = '회원이 사용됩니다. –

1

Widget& operator=(int rhs)

이 당신이 위젯에 INT을 할당 할 수 있습니다 mywidget = 3;

Widget& operator=(Widget const & rhs)을 작성하십시오. mywidget = mywidget2 = mywidget3; 행으로 호출됩니다.

operator=(Widget const & rhs)이 필요합니다. 기본값은 정상적으로 수행되어야합니다.

또한 예를 들어 다음과 같이 추가하는 것이 좋습니다. cout << "operator=(int rhs)\n";을 사용자 지정 연산자에 추가하면 코드에서 전혀 호출되지 않았 음을 알 수 있습니다.

4

operator=을 정의해야하는지, 그리고 그렇게 할 때 개체에 대한 참조를 반환해야하는지 여부에 대한 질문에는 두 가지 개념이 있습니다.

당신은 세 가지의 규칙을 고려해야합니다 : 당신이 복사 생성자, 할당 연산자 또는 당신이 그 (것)의 세 가지를 정의해야소멸자 중 하나를 정의합니다. 이 규칙의 근거는 소멸자를 제공해야한다는 것은 리소스를 관리한다는 의미이며 복사 생성자지정 연산자은 리소스를 관리하지 않는다는 것을 의미합니다. 예를 들어, 원시 포인터를 통해 메모리를 보유하고 있다면 소멸자에서 메모리를 해제해야합니다. 복사 생성자할당 연산자을 제공하지 않으면 포인터가 복사되고 두 개의 다른 개체가 포인터가 보유한 메모리를 해제하려고 시도합니다.

포인터가 가장 일반적인 예이지만 이것은 리소스에 적용됩니다. 예외는 입니다. 복사 구성 및 할당 -하지만 다시는 당신이 어떻게 든 이 (가) 이 (가)으로 정의되어 있습니다.

질문의 두 번째 부분에서 또는 개체에 대한 참조를 반환해야하는지 여부를 확인해야합니다. 그 이유는 다른 모든 연산자 오버로드와 마찬가지로 기본 유형의 기존 연산자가 수행하는 작업을 모방하는 것이 좋습니다. 때로는 과부하 연산자 인 의 경우는 int으로 처리하고으로 처리합니다.

관련 문제