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 (); 이름없는 객체로 생성자를 호출하고 함수는 생성 된 객체에 대한 참조를 반환합니다 (암시 적). 그게 다야 …