operator ++ - *this rückgabe
-
Stromberg schrieb:
Ist meine Vorstellung jetzt korrekt, wie denkt ihr euch das im Kopf?
Hab nicht ganz verstanden, was du meinst

Für mich sind jedenfalls Referenzen das selbe wie Pointer - nur eben mit einer anderen Schreibweise. Und Pointer selber beinhalten ja nur die Adresse von einer Variablen, dabei können natürlich auch mehrere Pointer dieselbe Adresse beinhalten. Aber ich will hier nicht Pointer erklären, für den Fall dass du dich da noch nicht so auskennst, kann dir vielleicht Binky weiterhelfen

-
ich hab das gefühlt, dich haben die referenzen jetzt endgültig verwirrt.

wenn man eine referenz zurückgibt, heißt dieses vor allem, dass man bei return kein neues objekt erstellt, sondern das objekt selber zurückliefert. in deinem schreib stil sähe das etwa so aus:
//für ein objekt nennen wir es a und den operator++ math a; //so sieht dann die eigentlich funktion aus: &[a] operator++() { ++A; return [a]; }es wird eben keine neue referenz oder variable erzeugt, sondern das objekt selber wird weiter genutzt.
allerdings ist es so, dass du bei zuweisung dann doch ein neues objekt erstellst.(um mal deinen code weiter zu nutzen):math a; math b; b=++a; //<- hier wird b nicht mit &a belegt, sondern mit einer kopie von a.das hat etwas damit zu tun, dass operator=() und der copy-ctor grundsätzlich mit einer const & als parameter versorgt werden.
die vorstellung mit der REF geht daher ein bisschen am sinn des ganzen vorbei.
-
Also jetzt blick ich irgendwie gar nimma so durch, vorhin hat hier irgendjemand folgenden link gepostet --> http://www.c-plusplus.net/forum/viewtopic-var-t-is-39454.html
Hab ich mir jetzt halt mal angeschaut, und dann kam der Code hier vor:#include <iostream> class foo { public: foo(int nr):m_nr(nr) {} foo & operator++ () // Präfix { ++m_nr; return *this; } const foo operator++ (int) // die Postfix-Version bekommt ein int-dummy Parameter { // um sie von der Präfix-Version unterscheiden zu können foo tmp(*this); ++(*this); // benuzt den Präfix-Operator return tmp; } private: int m_nr; }; int main() { return 0; }Das verstehe ich nicht, warum wird beim Postfix Operator keine Referenz zurückgegeben. Wenn ich bis jetzt alles richtig gecheckt habe, dann heißt es doch "freies Objekt ohne Referenz --> KOPIE --> Zeitaufwand", "Referenz --> keine KOPIE --> nicht so großer Zeitaufwand"....so mhm??? Also würde ich das so machen:
#include <iostream> class foo { public: foo(int nr):m_nr(nr) {} foo & operator++ () // Präfix { ++m_nr; return *this; } const foo & operator++ (int) // die Postfix-Version bekommt ein int-dummy Parameter { // um sie von der Präfix-Version unterscheiden zu können foo &tmp(*this); ++(*this); // benuzt den Präfix-Operator return tmp; } private: int m_nr; }; int main() { return 0; }Und was ich noch nicht verstehe warum wird da extra ein "foo tmp" Objekt angelegt, es würde doch reichen wenn man einfach "++(*this)" macht und dieses dann return (der Rückgabetyp muss dann halt eine Referenz sein..schon klar).
Kann mir nochmal jemand helfen?
MfG
Stromberg
-
Du scheinst an der Stelle ein Verständnisproblem mit dem Postfix-Inkrement zu haben. Dieser liefert das Objekt vor der Inkrementierung zurück. Da zu dem Zeitpunkt der Rückgabe aber das Objekt bereits inkrementiert wurde, muss das Objekt vor der Inkrementierung logischerweise eine Kopie sein. Ein Objekt kann nicht gleichzeitig den neuen und alten Wert besitzen

Und da "tmp" eine lokale Variable innerhalb der Funktion ist, die am Ende der Funktion zerstört wird, kannst Du keine Referenz auf sie zurückgeben. D.h. Du kannst schon, aber das wird nicht das erwartete Ergebnis bringen.
-
Das hat eine ganz einfache Ursache:
Wenn mana=x++schreibt, will man an der Stelle des "x++", dass das x erhöht wird, aber man will noch mit dem ursprünglichen Wert weiterarbeiten. Deshalb wird normalerweise bei "x++" intern das x erhöht und ein neues Objekt zurückgegeben, das dem x vor dem Erhöhen entspricht.Hier
const foo & operator++ (int) { foo &tmp(*this); ++(*this); return tmp; }ist "tmp" eine Referenz, die das aktuelle Objekt referenziert. Das Objekt wird um eins erhöht und die Referenz zurückgegeben. Das Problem dabei ist, dass dann schon das "erhöhte" Objekt zurückgegeben wird (es wird ja das aktuelle zurückgegeben und "tmp" verweist ja auf "*this").
Also legt man normalerweise eine Kopie an:foo tmp( *this );, was ein vollwertiges neues Objekt mit dem Zustand von x ist. Dann erhöht man das richtige x++(*this)und gibt das Objekt mit dem nicht-erhöhten Zustand zurückreturn tmp;. Eine Referenz darauf zurückgeben, würde nicht funktionieren, da das neu erzeugte Objekt beim Verlassen der Funktion zerstört wird - die Referenz würde ins Nirvana zeigen.
-
Ah okay, is klar, des hab ich wirklich ma verstanden.
-
MH ne doch nicht ganz, warum verwndet man nur beim postfix operator ein "const"?
MfG
Stromberg
-
Siehe mein Codebeispiel auf Seite 2. int verhält sich auch so, also muss du dafür sorgen, dass dein math das selbe Spiel spielt.
-
Noch eine neue Frage. Wieder das Beispiel von dem Link:
class foo { public: foo(int nr):m_nr(nr) {} foo & operator++ () // Präfix { ++m_nr; return *this; } const foo operator++ (int) // die Postfix-Version bekommt ein int-dummy Parameter { // um sie von der Präfix-Version unterscheiden zu können foo tmp(*this); ++(*this); // benuzt den Präfix-Operator return tmp; } private: int m_nr; };Der Postfix Operator nutzt doch den Präfix Operator nä? Wäre es nicht schneller wenn man ihm Postfix Operator einfach auch "++m_nr" reinschreibt, anstatt "++(*this)", sodass nicht extra der Präfix Operator aufgerufen werden muss? Oder ist das total egal?
MfG
Stromberg
-
Stromberg schrieb:
Der Postfix Operator nutzt doch den Präfix Operator nä? Wäre es nicht schneller wenn man ihm Postfix Operator einfach auch "++m_nr" reinschreibt, anstatt "++(*this)", sodass nicht extra der Präfix Operator aufgerufen werden muss? Oder ist das total egal?
Theoretisch ja, praktisch nein.
Compiler sind nicht dumm - wenn sie sehen dass ++*this nichts anderes als ein ++n macht, dann optimieren sie das dahingehend.
-
Ah okay, dann kann ich ja dadurch wenigstens den compilier Vorgang schneller machen ^^

-
Stromberg schrieb:
Der Postfix Operator nutzt doch den Präfix Operator nä? Wäre es nicht schneller wenn man ihm Postfix Operator einfach auch "++m_nr" reinschreibt, anstatt "++(*this)", sodass nicht extra der Präfix Operator aufgerufen werden muss? Oder ist das total egal?
Theoretisch könnte es schneller sein, aber bei der Größe wird der Aufruf sowieso inline aufgelöst und dann sind beide Versionen identisch. ABER: Wenn du kompliziertere Klassen hast, wird auch der Code zum Inkrementieren aufwendiger - und dann ist es günstiger, nur eine Stelle anzupassen, als wenn du immer darauf achten müsstest, daß Präfix- und Postfix-Inkrement das selbe machen.