Kopierkonstruktor, Zuweisungsoperator
-
Also das kann ich nicht unterschreiben. Code wie dieser macht mir immer Bauchweh.
Ok hasst recht, ich berichtige:
Macht keinen Sinn, auf den Rueckabewert einer zuweisung zu schreiben ...
Ciao ...
-
RHBaum schrieb:
bei den anderen binaeren verkettenbaren operatoren hasst natuerlich vollkommen recht ...
Sofern es sich um Assignment Operatoren handelt, dann 'foo&', bei Non-Assignment 'const foo'.
RHBaum schrieb:
Nur weil es bei den Pods geht, soll es mit meinen Klassen auch gehen
Wer spricht denn von PODs? Obwohl es bei denen ja das Gleiche ist, wie mit primitiven Typen. Also ein weiteres Argument gegen 'const foo&'.
RHBaum schrieb:
obwohls keinen Sinn macht, find ich irgendwie nicht recht nen gutes Argument
Wieso macht es keinen Sinn? Hast du noch nie Code geschrieben, in dem Folgendes gemacht wurde?
b = a = 0;Nein? Dann kannst du dir vielleicht vorstellen, dass es Leute gibt, die sowas schon verwendet haben (mich eingeschlossen). Ändere nicht die Prinzipien einer Sprache, nur damit sie dir besser passt, und du damit andere mit deinem Erfahrungsschatz einschränkst.
RHBaum schrieb:
und wenn wer wirklich schreibt (x=y)=Z halt ich das fuer nen Denk oder tippfehler, wo der compiler ruhig maulen sollte ...
Nö. Der Compiler soll maulen, wenn's syntaktisch nicht korrket ist, und nicht wenn sich jemand vertippt oder 'nen Denkfehler hat. Niemand hat gesagt, dass C++ eine leichte Sprache ist. Und Fallen gibts überall. Ich denke da nur an
if (a = 0)Um solchen Sachen vorzubeugen, schreiben ja einige Leute die Konstante auf die linke Seite, also
if (0 = a)Aber was machst du, wenn du zwei l-values hast?
C++ ist nunmal keine idiotensichere Sprache, und das wird sie auch nie werden. Also versuche erst gar nicht, eine daraus zu machen.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.
-
Wieso macht es keinen Sinn? Hast du noch nie Code geschrieben, in dem Folgendes gemacht wurde?
C/C++ Code:
b = a = 0;
C/C++ Code:Natuerlich verwende ich das auch ....
und das ist selbst mit dem const correct, weil es ja als
b = (a = 0) aufgeloest wird, und nicht als (b = a) = 0den ruckgabewert verwendest du schon, ich natuerlich manchmal auch, aber ich schreib nie darauf rum, das mein ich damit ...
Ich lass mich aber immer noch belehren:
nenn mir nen Fall, wo man auf die Rueckgabe einer Zuweisung rumschreibt, und es auch noch Sinn macht.Wer spricht denn von PODs? Obwohl es bei denen ja das Gleiche ist, wie mit primitiven Typen.
Vielleicht lieg ich da im Begriff falsch, aber bei PODs (plain old data) gehoerten bei mir die primitiven typen immer mit rein ... oder lieg ich da falsch ?
und da es fuer die nicht primitiven, aber doch PODs (struct union pointer) auch gilt, hab ichs halt auch so ausgedrueckt ...Ciao ...
-
RHBaum schrieb:
Natuerlich verwende ich das auch ....
und das ist selbst mit dem const correct, weil es ja als
b = (a = 0) aufgeloest wird, und nicht als (b = a) = 0Achso, da hab ich dich missverstanden. Dachte, du hättest was gegen 'x = y = z'. Dass '(x = y) = z' wenig Sinn macht, hatten wir ja schon geklärt.
RHBaum schrieb:
nenn mir nen Fall, wo man auf die Rueckgabe einer Zuweisung rumschreibt, und es auch noch Sinn macht.
Was Sinn macht oder nicht, ist natürlich relativ. Ich könnte mir aber Folgendes Szenario vorstellen:
void mach_irgendwas(foo& a) { //... } a = lese_irgendwas(); mach_irgendwas(a);Ich würde immer zu dieser Schreibweise tendieren, auch weil's einfach übersichtlicher ist. Wer dennoch eine etwas kompaktere Schreibweise bevorzugt, kann dies natürlich machen. Diese Freiheit bietet C++ nunmal.
mach_irgendwas(a = lese_irgendwas());Diese Möglichkeit würde mit const foo& als Rückgabe vom op= nicht mehr funktionieren.
RHBaum schrieb:
Vielleicht lieg ich da im Begriff falsch, aber bei PODs (plain old data) gehoerten bei mir die primitiven typen immer mit rein ... oder lieg ich da falsch ?
Laut Wiki nicht. Ich dachte eigentlich immer, dass PODs Strukturen sind, die keine selbstdefinierten Konstruktoren und Operatoren haben. Aber offensichtlich gehören die primitiven Typen auch dazu. Man lernt halt nie aus.
Naja, wie auch immer. Ich sprach allerdings nur von primitiven Typen. Dass Strukturen, die keinen selbstdefinierten op= haben und wiederum nur PODs als Member, sich genauso verhalten, sollte einen ja noch zusätzlich nachdenklich machen, dass man mit 'const foo&' bestehende Regeln bricht.
-
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.