rvalue reference
-
Also sind enum-Konstanten lvalues.
Enumeratoren sind keine Objekte.
Wie soll man das verstehen ohne zu wissen, was ein rvalue ist?
Gar nicht. Habe ich das behauptet?
string s; return s; // <-- s ist kein xvalue
Die Aussage ist natürlich Blödsinn, und kann aus meinen soweit ich sehe nicht abgeleitet werden. s ist ein Objekt mit Namen. Daher ist der Ausdruck mit seinem Namen ein lvalue.
zjraw schrieb:
prvalues sind alle Namenlosen Objekte (bspw. Temporaries).
Ok, also
string s = "..."; s[0] // <- prvalue
Gut, hier bin ich zu pauschal gewesen.
Aber ich habe mich explizit auf lvalue Referenzen als lvalues bezogen. Das beinhaltet Funktionen, die lvalue Referenzen zurückgeben. Reicht das nicht als
Fallunterscheidung?Und das ist alles noch relativ einfach. Auch wenn ich das zu verallgemeinern versucht habe, ist es an sich wirklich einfach. Da gibt es noch viel schwierigeres.
-
Sone schrieb:
die Begriffe sind doch eigentlich selbst redend.
lvalues: Das sind alle Objekte/Referenzen mit Namen und alle lvalue-Referenzen
Aha. Der Name kommt aber daher, dass l-values links in einer Zuweisung stehen.
Trotzdem kann ich auch einem temporary Dinge zuweisen, wenn ich mag und das Ding einen entsprechend überladenen op= hat. Das macht das temporary aber noch nicht zu einem l-value. Also ist der Name nicht selbstredent.//edit und welche namentliche Bedeutung pr, gl oder x haben soll...naja.
-
otze schrieb:
Aha. Der Name kommt aber daher, dass l-values links in einer Zuweisung stehen.
Trotzdem kann ich auch einem temporary Dinge zuweisen, wenn ich mag und das Ding einen entsprechend überladenen op= hat. Das macht das temporary aber noch nicht zu einem l-value. Also ist der Name nicht selbstredent.Nein, das ist er leider tatsächlich nicht, auf den zweiten Blick.
//edit und welche namentliche Bedeutung pr, gl oder x haben soll...naja.
Das ist doch alles im Standard erklärt!
pure rvalues, generalized lvalues und expiring values. Alles gut gewählt.
-
Sone schrieb:
Das ist doch alles im Standard erklärt!
Und jtzt geh bitte einen Schritt zurück von deinem Monitor, schließe die Augen, überlege dir was du da geschrieben hast, und was mein Kritikpunkt war. Also erklären wir jetzt Dinge mit dem Standard, welcher Begriffe einführt, die so selbstredent sind, dass wir sie wieder im Standard nachschlagen müssen? Überlege dir, ob das ein gute Strategie ist.
Und zu deinem "gut gewält". "pure" ist wohl eines der mehrdeutigsten Begriffe überhaupt, x ist eine der dümmsten Abkürzungsbuchstaben überhaupt (x kann auch einfach als Platzhalter gebraucht werden oder steht im zweifelsfall für so gut wie jedes Wort im Lexikon das mit ex- beginnt. ).
Und du brauchst mir nicht erklären, was die Dinger bedeuten und wie man sie unterscheidet. Das interessiert mich nicht(weil ich es entweder weiß, oder es vom eigentlichn Punkt ablnken würde). Was mich interessiert ist: Es ist ein schlechtes Zeugnis für eine Sprache, wenn neue zentrale Sprachfeatures ohne Benutzung des Standards nicht erklärbar sind. Stell dir einfach mal vor, du arbeitest und ein Kollege fragt dich in der Kaffeepause, wie das nochmal mit den rvalue referenzen war. "Kein Problem, wir sehen gleich im Standard nach, das ist alles ganz einfach"? Eher nicht.
-
zjraw schrieb:
Und ich wäre immer noch daran interessiert, die Ausgabe http://ideone.com/rsHZgs zu verstehen.
gut, ich gehe das mal Schritt für Schritt durch und versuche mit dem Standard zu erklären, was passiert.
A const& i = hi(A());
Gut. Zuerst wird die Referenz (der Funktionsparameter von
hi
) an die Temporary gebunden. Selbstredend. Anschließend wird diese Referenz zurückgegeben. Das ist eine Dangling Reference, ein Klassiker.A const& i = static_cast<A const&>(A());
Das hier ist interessant. Du hast bereits das Zitat gebracht:
§5.2.9/4 schrieb:
Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (8.5).
The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion.Das heißt, es wird sozusagen die Referenz erzeugt, es gibt eine Lebenszeitverlängerung, aber diese beschränkt sich auf diese "temporäre Referenz" - und die Zuweisung dieser Referenz zu i ist einfach:
then the reference is bound to the initializer expression lvalue
Das heißt, nach der Zeile ist der Scope der temporären Referenz vorbei, und es gibt kein Objekt mehr. Die Referenz i ist ungültig.
A const& i = std::move(A());
Wie schon früher von mir erklärt, ist das effektiv dasselbe wie dein unterstes Beispiel:
A const& i = static_cast<A&&>(A());
Du weist also i ein xvalue zu. Nach Standard ist das dasselbe wie oben - es wird die temporäre Referenz erzeugt, Lebenszeitverlängerung für die Zeile, und dann:
the reference is bound to the value of the initializer expression
Also für beide Fälle wieder keine Lebenszeitverlängerung.
Das heißt, alle vier Beispiele müssten
CD hi
ausgeben- und der Compiler hat Unrecht. Das wäre fatal, ich kann mir kaum vorstellen das etwas so fundamentales falsch implementiert wird.
Theoretisch. Mit Sicherheit habe ich es falsch interpretiert. Sicher weiß camper es besser. Also, falls jemand Lust hat, mir einzureiben wie wenig ich den Standard verstehe, nur her damit...
-
Stell dir einfach mal vor, du arbeitest und ein Kollege fragt dich in der Kaffeepause, wie das nochmal mit den rvalue referenzen war. "Kein Problem, wir sehen gleich im Standard nach, das ist alles ganz einfach"? Eher nicht.
Deswegen hat Marc++us (oder wer war das noch) es auch passend erklärt: Man wartet erst einmal, wie sich C++11 in der Praxis bewährt. Deswegen nutzen das viele in Hobby-Projekten und in diversen Code-Schnipseln im Forum, aber keine eurer Firmen nutzt C++11 so konsequent.
Oder? Würde mich wundern.
Es ist ein schlechtes Zeugnis für eine Sprache, wenn neue zentrale Sprachfeatures ohne Benutzung des Standards nicht erklärbar sind.
Deswegen ist C++ ja auch für die Verrückten, zum dritten mal.
Und zu deinem "gut gewält". "pure" ist wohl eines der mehrdeutigsten Begriffe überhaupt, x ist eine der dümmsten Abkürzungsbuchstaben überhaupt (x kann auch einfach als Platzhalter gebraucht werden oder steht im zweifelsfall für so gut wie jedes Wort im Lexikon das mit ex- beginnt. ).
Wie willst du es denn griffig abkürzen, sodass man es oft im Standard verwenden kann? expvalue? Klingt ebenso bescheuert und erinnert an "exponential". exvalue hört sich nach Ex-Partner an, und expiring-value ist zu lang und kein geschlossener Term.
-
ideone hat Unrecht. Übrigens tritt der Fehler erst ab g++ 4.7 auf, mit 4.6 wird es noch richtig gemacht (getested rückwärts bis 3.4.6, dann nat. ohne den rvalue-Teil des Codes). clang 3.3 bringt auch die richtige Reihenfolge.
C++ Standard Core Language Issue #1376
Wer Lust hat, sucht noch den entsprechenden bug-Report bei gcc raus - ich nehme mal an, der existiert schon.
-
C++ Standard Core Language Issue #1376
Der Fix den sie vorschlagen ist falsch. Die Variable muss temporär sein. Ich sehe auch keine Irritation bei dem Paragraph, so wie ich ihn oben offensichtlich richtig interpretiert habe, ist alles eindeutig. Auch Referenzen können temporär sein.
camper schrieb:
Wer Lust hat, sucht noch den entsprechenden bug-Report bei gcc raus - ich nehme mal an, der existiert schon.
Hier, ist auch für GCC 4.7 gemeldet: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52202
-
out, wieso tust du uns das an??
-
Nathan schrieb:
out, wieso tust du uns das an??
Wieso antun? Ich froh, aus diesem Thread habe ich viel gelernt.
-
Wenn man seinem Kollegen erklärt was rvalues sind, dann sagt man "rvalues sind Temporaries. Denen kann man Resourcen klauen weil das effizient ist und die eh gleich wieder verschwinden". Dann nennt man noch kurz die &&-Syntax und das fehlende const und fertig. Der Kollege kann dann rvalues benutzen ohne den Standard gelesen zu haben und ohne je von lvalues gehört zu haben. Es ist einfach intuitiv klar.
Wenn man natürlich einen Compiler schreibt oder ein Klugscheißer ist, dann muss man klare Regeln haben an denen man beweisen kann, dass ein gegebener Ausdruck oder ein Verhalten korrekt ist und dann muss man etwas weiter ausholen.
So ähnlich wie ein C-Programmierer der fragt "Was ist ein vector?". Das ist ein dynamisches Array. Ganz einfach. Wenn man das allerdings in Code hinschreiben sollte wird es doch etwas lang.
Genauso versucht das Standardkommitee, dass das was man intuitiv annimmt auch das ist, was die Compiler tun müssen, aber sie müssen es ausformulieren. Vielleicht sollte mal jemand einen intuitiven Standard schreiben.Wenn man C++ betreibt, indem man jede Zeile analysiert und dahinter die entsprechenden Standardreferenzen in den Kommentar schreibt, dann ist C++ tatsächlich für Verrückte. Wenn man ein bisschen logisch denken kann, dann kann man C++ einfach so benutzen ohne verrückt zu werden.
-
Wenn man ein bisschen logisch denken kann, dann kann man C++ einfach so benutzen ohne verrückt zu werden.
Nein, kann man nicht. Das stellst du dir so einfach vor, aber das ist es nicht. Ab einem bestimmten Punkt ist es eben nicht mehr intuitiv, und ab diesem Punkt fängt dieses Paragraphengefuchtel an.
sagt man "rvalues sind Temporaries."
Das klingt vielleicht schön. Aber wenn es so einfach wäre, dann hätten wir jetzt keinen Sechs Seiten langen Thread. Schon mal daran gedacht?
-
Sone schrieb:
Wenn man ein bisschen logisch denken kann, dann kann man C++ einfach so benutzen ohne verrückt zu werden.
Nein, kann man nicht. Das stellst du dir so einfach vor, aber das ist es nicht. Ab einem bestimmten Punkt ist es eben nicht mehr intuitiv, und ab diesem Punkt fängt dieses Paragraphengefuchtel an.
Doch kann man. Die Sprache hat einige Anomalien, aber in normalen Programmen tauchen die nie auf.
-
out schrieb:
Sone schrieb:
Ist dir bewusst, dass eine rvalue reference (genau wie eine const lvalue reference) die Lebenszeit eines prvalues verlängert?
Joa. Das dürfte bei Funktionsüberladung lustig werden.
Hierzu hab ich was gefunden: http://www.c-plusplus.net/forum/281972
Sone schrieb:
Also sind enum-Konstanten lvalues.
Enumeratoren sind keine Objekte.
Im Standard steht irgendwo, dass alles, was Speicher verbraucht, ein Objekt ist, außer Funktionen. Ein Enumerator = int = braucht Speicher.
Nathan schrieb:
out, wieso tust du uns das an??
nwp3 schrieb:
Wenn man seinem Kollegen erklärt was rvalues sind, dann sagt man "rvalues sind Temporaries. Denen kann man Resourcen klauen weil das effizient ist und die eh gleich wieder verschwinden". Dann nennt man noch kurz die &&-Syntax und das fehlende const und fertig. Der Kollege kann dann rvalues benutzen ohne den Standard gelesen zu haben und ohne je von lvalues gehört zu haben. Es ist einfach intuitiv klar.
+1
nwp3 schrieb:
Wenn man ein bisschen logisch denken kann, dann kann man C++ einfach so benutzen ohne verrückt zu werden.
Manche sind auch schon vorher verrückt, nicht wahr, Sone.
-
nwp3 schrieb:
Wenn man seinem Kollegen erklärt was rvalues sind, dann sagt man "rvalues sind Temporaries.
Und wo ist da der Part mit perfect forwarding?
//edit und der Teil mit der Lebenszeit von temporaries die an T&& gebunden sind?
Ui, schon sind wir bei diesem Thread.
-
otze schrieb:
nwp3 schrieb:
Wenn man seinem Kollegen erklärt was rvalues sind, dann sagt man "rvalues sind Temporaries.
Und wo ist da der Part mit perfect forwarding?
Tempalte+&& = universal reference + std::forward
Sonst rvalue + std::move. Dass int&& i ein lvalue ist ist vielleicht verwirrend, aber deshalb immer moven.//edit und der Teil mit der Lebenszeit von temporaries die an T&& gebunden sind?
Ui, schon sind wir bei diesem Thread.Das ist absolut identisch mit T const& aus C++03.
-
Im Standard steht irgendwo, dass alles, was Speicher verbraucht, ein Objekt ist, außer Funktionen.
Ein Objekt ist definiert als
An object is a region of storage. [ Note: A function is not an object, regardless of whether or not it occupies storage in the way that objects do. —end note ]
Da hast du das wohl her. Deine Pauschalaussage ist falsch, denn Referenzen sind auch keine Objekte, mögen sie auch Speicher belegen (oder auch nicht).
Ich glaube aber, das Missverständnis liegt in dem Begriff "Enumerator". Ich und der Standard bezeichnen damit die in einer Enumeration deklarierten Konstanten.
The identifiers in an enumerator-list are declared as constants, and can appear wherever constants are required. An enumerator-definition with = gives the associated enumerator the value indicated by the constant-expression.
Das alles heißt nicht, dass sie Objekte sind, denn Deklarationen oder Definitionen sind nicht an Objekte gebunden. Es sind einfach Konstanten mit einem Typ, einem Namen und einem Wert. Heißt immer noch nicht, dass sie Objekte sind.
Du wirst wohl eher Objekte vom Enumerations-Typ gemeint haben.
enum foo {a, b}; // a und b sind Enumeratoren. foo bar;// bar ist ein Objekt vom unterliegenden Typ
Manche sind auch schon vorher verrückt, nicht wahr, Sone.
Völlig richtig. Ich verstehe gar nicht, wieso du dass amüsant findest. Das war eigentlich eher als Kompliment gemeint.