A () = A ()-왜 컴파일됩니까? A {}; int main() { A() = A();

class A {};

int main() {
 A() = A();
 return 0;
}

이 코드가 컴파일되는 이유는 무엇입니까? 할당 연산자의 왼쪽에 lvalue를 배치해야한다는 오류가 없어야하지 않나요? A () lvalue입니까? g ++ 4.7 버전



답변

기본 제공 유형의 경우 맞습니다. 기본 제공 할당 연산자에는 왼쪽에 수정 가능한 lvalue 가 필요합니다 .

그러나 이것은 내장 연산자를 사용하지 않고 클래스에 의해 암시 적으로 선언 된 오버로드입니다. 이것은 다음과 같은 멤버 함수입니다.

A().operator=(A());

멤버 함수는 rvalue에서 호출 될 수 있습니다 .


답변

정말로 원한다면 C ++ 11로 컴파일하지 않도록 만들 수 있습니다.

class A {
    template <typename T>
    void operator=(T&&) && = delete; // no op= for rvalues

    // generate other special members normally
    A() = default;
    A(A const&) = default;
    A(A&&) = default;
    ~A() = default;
    // op= only for lvalues
    A& operator=(A&&) & = default;
    A& operator=(A const&) & = default;
};

int main() {
 A() = A(); // error
 return 0;
}

( 실제 예 )

다양한 형식 의 선언 끝에 있는 &and &&(일명 ref 한정자)에 유의하십시오 operator=. 이렇게하면 각각 lvalue 및 rvalue에 대해 이러한 선언이 선택됩니다. 그러나 rvalue 버전을 과부하 해결로 선택하면 프로그램이 삭제되기 때문에 프로그램이 잘못 구성됩니다.

그러나 기본적으로 생성 된 operator =에는 ref 한정자가 없습니다. 즉, lvalue와 rvalue 모두에 대해 호출 될 수 있습니다. 이것이 질문의 코드 A()가 rvalue 임에도 불구하고 컴파일되는 이유 입니다.


답변

C ++ 컴파일러는 모든 클래스에 기본 생성자를 제공합니다. 이것이 바로 코드와 관련하여 A () = A (); 이름없는 객체로 생성자를 호출하고 함수는 생성 된 객체에 대한 참조를 반환합니다 (암시 적). 그게 다야 …


답변