class A {};
int main() {
A() = A();
return 0;
}
Dlaczego ten kod się kompiluje? Czy nie powinno być błędu polegającego na umieszczeniu po lewej stronie operatora przypisania lwartość? Czy A () lwartość? Wersja g ++ 4.7
Dla typów wbudowanych, byłbyś poprawne: wbudowany operator przypisania wymaga modyfikowalna lwartość na lewym skrzydle.
Jednak nie jest to użycie operatora wbudowanego, ale przeciążenie, które jest niejawnie zadeklarowane przez klasę. To jest funkcja składowa, równoważna
A().operator=(A());
a funkcje składowe mogą być wywoływane na rvalues .
operator=
nie masz na myślioperator()
), ale nie ma to wiele wspólnego z pytaniem. Przykład nie robi nic z wynikiem przypisania.A()
nie wywołujeoperator()
, tworzy obiekt typuA
.Jeśli naprawdę chcesz, możesz uniemożliwić kompilację z 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; }
( przykład na żywo )
Zwróć uwagę na
&
and&&
(aka ref-Qualifiers) na końcu deklaracji różnychoperator=
form. To sprawia, że te deklaracje są wybierane odpowiednio dla lvalues i rvalues. Jednak wersja rvalue wybrana przez rozwiązanie przeciążenia powoduje, że program jest nieprawidłowo sformułowany, ponieważ został usunięty.Domyślnie wygenerowany operator = nie ma jednak żadnego kwalifikatora ref, co oznacza, że można go wywołać zarówno dla lvalues, jak i rvalues; dlatego kod w pytaniu kompiluje się, mimo że
A()
jest wartością r.źródło
Kompilator C ++ dostarcza wszystkim klasom domyślnego konstruktora, to właśnie się dzieje, w odniesieniu do twojego kodu, kiedy powiesz A () = A (); po prostu wywołuje konstruktor z bezimiennym obiektem, a funkcja zwraca odniesienie do skonstruowanego obiektu (niejawne). Otóż to...
źródło