class A {};
int main() {
A() = A();
return 0;
}
Por que este código compila? Não deveria haver algum erro que no lado esquerdo do operador de atribuição deve ser colocado lvalue? É A () lvalue? versão g ++ 4.7
Respostas:
Para os tipos internos, você estaria correto: o operador de atribuição interno requer um lvalue modificável no lado esquerdo.
No entanto, isso não está usando o operador integrado, mas a sobrecarga que é declarada implicitamente pela classe. Esta é uma função de membro, equivalente a
A().operator=(A());
e as funções de membro podem ser chamadas em rvalues .
operator=não queira operator()), mas não tem muito a ver com a pergunta. O exemplo não faz nada com o resultado da atribuição.
A()não chama operator(), ele constrói um objeto do tipo A.
Se você realmente quiser, pode fazer com que ele não seja compilado com 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;
}
( exemplo ao vivo )
Observe o &e &&(também conhecido como qualificadores ref) no final das declarações dos vários operator=formulários. Isso faz com que essas declarações sejam selecionadas para lvalues e rvalues respectivamente. No entanto, a versão rvalue, quando selecionada pela resolução de sobrecarga, faz com que o programa fique malformado porque foi excluído.
O operador padrão gerado =, entretanto, não possui nenhum qualificador ref, o que significa que pode ser chamado para lvalues e rvalues; é por isso que o código da pergunta é compilado, embora A()seja um rvalue.
O compilador C ++ fornece a todas as classes um construtor padrão, é o que acontece, com relação ao seu código, quando você diz A () = A (); ele apenas invoca o construtor com um objeto sem nome e a função retorna a referência ao objeto construído (implícito). É isso aí...