A () = A () - warum wird kompiliert?

85
class A {};

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

Warum wird dieser Code kompiliert? Sollte es nicht einen Fehler geben, dass auf der linken Seite des Zuweisungsoperators ein Wert platziert werden sollte? Ist A () lWert? g ++ 4.7 Version

scdmb
quelle

Antworten:

88

Bei eingebauten Typen sind Sie richtig: Der eingebaute Zuweisungsoperator erfordert einen veränderbaren Wert auf der linken Seite.

Hierbei wird jedoch nicht der integrierte Operator verwendet, sondern die von der Klasse implizit deklarierte Überladung. Dies ist eine Mitgliedsfunktion, die äquivalent zu ist

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

und Mitgliedsfunktionen können für rWerte aufgerufen werden .

Mike Seymour
quelle
7
Ist es nicht eine Kopierinitialisierung?
Sternenstaub
13
@Named: Nein, die Zuordnung ist keine Initialisierung.
Mike Seymour
1
@ paul23: Das stimmt (vorausgesetzt du meinst operator=nicht operator()), hat aber nicht viel mit der Frage zu tun. Das Beispiel hat nichts mit dem Ergebnis der Zuweisung zu tun.
Mike Seymour
3
@ paul23 A()ruft nicht auf operator(), es erstellt ein Objekt vom Typ A.
Interjay
3
Es kann keine Initialisierung sein, da keine Deklaration vorliegt.
Kos
32

Wenn Sie wirklich wollen, können Sie dafür sorgen, dass es nicht mit C ++ 11 kompiliert wird:

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; 
}

( Live-Beispiel )

Beachten Sie das &und &&(auch als Ref-Qualifier bezeichnet) am Ende der Deklarationen der verschiedenenoperator= Formulare. Dadurch werden diese Deklarationen für l-Werte bzw. r-Werte ausgewählt. Die rvalue-Version führt jedoch bei Auswahl durch Überlastungsauflösung zu einer Fehlbildung des Programms, da es gelöscht wird.

Der standardmäßig generierte Operator = hat jedoch kein Ref-Qualifikationsmerkmal, was bedeutet, dass er sowohl für l-Werte als auch für r-Werte aufgerufen werden kann. Deshalb wird der Code in der Frage kompiliert, obwohl A()es sich um einen Wert handelt.

R. Martinho Fernandes
quelle
1

Der C ++ - Compiler stellt allen Klassen einen Standardkonstruktor zur Verfügung. Dies geschieht in Bezug auf Ihren Code, wenn Sie A () = A () sagen. Es ruft nur den Konstruktor mit einem namenlosen Objekt auf und die Funktion gibt einen Verweis auf das konstruierte Objekt zurück (implizit). Das ist es...

Praveen Kumar
quelle