Kopierkonstruktor, Zuweisungsoperator
-
groovemaster schrieb:
camper schrieb:
im übrigen ist (x=y)=z ja nur undefiniert, falls x einen trivialen zuweisungsoperator hat
Wieso das? Irgendwie steh ich im Moment auf'm Schlauch.
das problem ist dorch, dass x zweimal zwischen zwei sequence points verändert wird, richtig?
ist nun zuweisungsoperator nicht trivial, handelt es sich um ganz normale funktionsaufrufe (nur mit operator schreibweise). alle seiteneffekte durch die initialisierung eines funktionsparameters müssen abgeschlossen sein, bevor die funktion selbst aufgerufen wird.
beispiel:
wir haben noch op<<= für streams überladen, so dass es sich wie op << verhält (beide geben ihren linken operanden weiter, so wie op= es tut).
dann wird niemand erwarten, dass(cout<<=a)<<=b;undefiniert ist. für builtins wäre es das aber.
-
Verstehe trotzdem noch nicht, was daran undefiniert sein soll. Der Compiler macht aus '(x = y) = z' im Grunde doch
x = y, x = zEgal, ob es sich um einen trivialen oder nicht-trivialen op= handelt, ist das doch definiert.

-
#include <iostream> int main() { int a, b = 1, c = 2; std::cout << ( ( a = b ) = c ) << std::endl; std::cout << a << std::endl; }in der ersten zeile wird auf jeden fall 2 ausgegeben. was in der 2. zeile steht, ist dagegen unbestimmt. der compiler darf hier machen, was er will.
-
Hast du zufällig eine Stelle im Standard parat, wo das beschrieben wird?
Ich dachte eigentlich, dass die Klammerung dafür sorgt, dass 'a = b' auf jeden Fall VOR 'a = c' durchgeführt wird. Sprich, dass am Ende a immer den Wert von c hat.
Oder was meinst du mit "der compiler darf hier machen, was er will"? Was könnte denn der Compiler hier theoretisch alles machen?
-
es scheint es genügt, dass x ein objekt oder ein enum ist, damit der ausdruck unproblematisch wird. Ich würde mich auf Kapitel 5 Abs.4 stützen:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior vallue shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behaviour is undefined.*Example:
i = v[i++]; // the behaviour is unspecified
i = 7, i++, i++; // i becomes 9i = ++i + 1; // the behaviour is unspecified
i = i + 1; // the value of i is incrementd*nun ist unspecified zwar nicht dasselbe wie undefined - in der praxis kann man sich die unterscheidung aber im grunde sparen. des speichern des neuen wertes in einer variable ist nur ein seiteneffekt der zuweisung. in der regel wird man sicher entweder y oder z vorfinden. da das speichern aber nicht unbedingt atomisch erfolgt (insbesondere für grosse typen), könnte es auch etwas anderes sein.
-
Nun, irgendwie überzeugt mich das nicht so richtig. Finde dazu im Standard aber auch nichts, was jetzt explizit dafür oder dagegen spricht. Hatte eigentlich gedacht, dass irgendwo die Auswertung von geklammerten Ausdrücken genau beschrieben wird. Vielleicht hab ich's aber auch nur übersehen. Und Seiteneffekte spielen hier ja keine Rolle. Entweder wird y zuletzt zugewiesen, oder z. Man sollte eigentlich meinen, dass dies durch die Klammerung eindeutig geregelt ist.