Soweit ich weiß, arbeitet C ++ von links nach rechts. Zum Beispiel, wenn ich das tue:
%Vor%C ++ beginnt zuerst an der äußersten linken Stelle (std :: cout), dann gibt es die & lt; & lt; operator, der das Zeichenfolgenliteral rechts ("output") übernimmt und auf das Objekt links vom Operator (std :: cout) legt. C ++ gibt dann das Objekt auf der linken Seite des Operators (std :: cout) zurück und setzt dann den Code fort, ein anderes & lt; & lt; Betreiber.
Was gibt der Operator "=" zurück?
Wenn ich das tue
%Vor%Ich dachte, der Operator "=" würde nur den linken oder rechten Operanden des "=" zurückgeben. Also, mit meiner Logik, in der Zeile der Gehaltsinitialisierung, wird das Gehalt mit dem Wert des Lohns initialisiert, dann gibt der "=" - Operator entweder Gehalt oder Gehalt (sagen wir Gehalt) zurück, dann weist es 9999,99 dem Gehalt zu, aber dem Lohn weg, es sollte seinen Wert von 5 behalten.
Aber wenn ich den Wert von "Gehalt" und "Lohn" nach der "Gehalts" -Initialisierung überprüfe, haben beide einen Wert von 9999,99. Wenn ich dieselbe Logik anwende, die ich mit std :: cout oben verwendet habe, sollte es nur eine Variable geben, entweder "Gehalt" oder "Lohn", mit einem Wert von 9999,99
Der Zuweisungsoperator ist von rechts nach links assoziativ und gibt im Allgemeinen seinen linken Operanden als Referenz zurück. Im Allgemeinen bedeutet dies, dass dies für alle eingebauten Typen, Bibliothekstypen, die ich mir vorstellen kann, gilt, und so wird erwartet, dass Sie Zuweisungsoperatoren schreiben.
Das bedeutet, dass
%Vor%Ist genau das Gleiche wie
%Vor% Beachten Sie, dass salary
in der zweiten Zeile hier auf wage
und nicht auf 9999.99
gesetzt wird. Die Unterscheidung ist hier nicht wichtig, aber in manchen Fällen kann es sein. Zum Beispiel (dank Justin Time zum Beispiel):
salary
erhält eindeutig einen Wert von 9998,99, aber es ist wichtig zu beachten, dass auch wage
dies tut; Wenn die Zuweisung stattdessen das richtige Argument zurückgibt, dann wäre wage
immer noch 9999,99, weil das temporäre stattdessen dekrementiert würde, nachdem die Zuweisung zum Lohn stattgefunden hat.
Wie Ben Voigt in den Kommentaren unten bemerkt, ist meine Antwort zwar korrekt, aber das Beispiel aus der Frage, die ich verwende, ist etwas irreführend. Dies liegt daran, dass =
trotz zweimaligem Auftreten des double salary = wage = 9999.99
-Tokens im fraglichen Code die Zuweisung nicht zweimal aufruft, sondern die Zuweisung aufruft und dann ein neues Double erstellt. Das Beispiel wäre besser wie folgt fortgesetzt:
Jetzt werden die Zuweisungsoperatoren wirklich verkettet, und alle meine vorherigen Kommentare über Vorrang und Rückgabe sind hier auf die zweite Codezeile anwendbar.
Weitere Informationen finden Sie in der Operatoren-Vorrangtabelle . Der Zuweisungsoperator =
ist eine Assoziation "von rechts nach links". Daher wird der Ausdruck effektiv wie folgt ausgewertet:
Mit wage = 9999.99
zuerst.
In Ihrem Beispiel
%Vor%... es gibt nur eine Zuweisung , nämlich
%Vor% Die anderen Instanzen von =
sind Teil der Initialisierungssyntax.
Die Zuweisung gibt eine Referenz auf das Objekt zurück, dem sie zugewiesen wurde, in diesem Fall wage
. Das Beispiel entspricht also
Wenn Ihr Beispiel für die Verwendung mehrerer Zuweisungen neu geschrieben wird,
%Vor%... dann wird es wichtig, dass Zuweisungsoperatoren rechtsassoziativ sind. Die letzte Zeile entspricht also
%Vor% ... wobei der geklammerte Ausdruck einen Verweis auf wage
zurückgibt.
Die Standardcontainer erfordern, dass ein benutzerdefinierter Zuweisungsoperator einen Verweis auf das zugewiesene Objekt zurückgibt. Die Kernsprache hat keine solche Anforderung, daher könnte man versucht sein, void
zu verwenden. I.e. garantierte Effizienz, keine Unterstützung für unheiligen, auf Seiteneffekten basierenden Code und eine präzisere Implementierung, die alle gut sind:
Um jedoch delete
oder default
einen Zuweisungsoperator zu geben, muss die Deklaration des Operators den Referenzrückgabetyp angeben:
Am dritten & amp; Greifende Hand, die ausführliche, nicht garantierte Effizienz und ungood-Unterstützung für Seiteneffekt-basierten Code operator=
kann ausgedrückt werden in Form einer separaten void
-Memberfunktion, die sogar ein Operator sein kann:
Ausdrücke haben einen Wert und einen Nebeneffekt . Der Wert (was Sie die "Rückgabe" nennen) wird für einen anderen Operator verwendet, für den dieser Ausdruck ein Operand von ist. (Es wird immer noch berechnet, auch wenn es keinen solchen Operator gibt). Der Prozess zum Finden des Werts eines Ausdrucks wird als -Wertberechnung bezeichnet.
Der Wert kann eine Wertkategorie enthalten. Der Nebeneffekt ist alles andere, wie das Aktualisieren eines Speicherplatzes oder das Aufrufen einer Funktion.
Im Allgemeinen kann der Nebeneffekt auftreten oder nicht, bevor der Wert in einem größeren Unterausdruck verwendet wird. In der Regel kann der Operator postfix- ++
einen recht großen Zeitunterschied zwischen dem Wert und dem Nebeneffekt haben.
Bei Zuweisungsausdrücken ist der Wert der linke Operand (mit dem Werttyp "lvalue"), und der Nebeneffekt ist, dass das vom linken Operanden angegebene Objekt so aktualisiert wird, dass es den Wert des rechten Operanden enthält. und der Nebeneffekt ist sequenziert vor die Wertberechnung, die garantiert, dass, wenn ein größerer Ausdruck den Wert verwendet, er einen Speicherplatz angibt, in dem bereits der neue Wert gespeichert ist.
>Wenn der Code wäre:
%Vor% Dann würden die Assoziativitätsregeln des Operators bedeuten, dass es salary = (wage = 9999.0);
ist. Der innere Ausdruck hat den Wert wage
mit dem Wert category lvalue
, und der Nebeneffekt des inneren Ausdrucks besteht darin, dass die Variable wage
9999.0
gespeichert hat und die Reihenfolge der Zuweisungsoperatoren das Ergebnis garantiert ist bereits dort gespeichert, bevor wir zum nächsten äußersten Ausdruck übergehen.
Dann haben wir salary = X
, wobei X
der Wert ist, der im vorherigen Absatz beschrieben wurde, d. h. er entspricht salary = wage;
Beachten Sie, dass Ihr tatsächlicher Code eine Deklaration ist und das erste =
-Zeichen in einer Deklaration nicht der Zuweisungsoperator ist. Stattdessen ist es ein grammatikalischer Marker, dass ein Initialisierer kommt; Ihr Code ist der gleiche wie:
Tags und Links c++