[Anfänger] Operator und Memoryleak ; C++0x Rvalue
-
Hallo,
1.) Um in C++ mehr Übung zu bekommen, bastle ich an einer kleinen Rechenbibliothek und da stieß ich auf folgendes Problem:
class Byte : public Number{ typedef char _byte; public: virtual Number* operator +(Byte *in) const; virtual Number operator +(Byte &in) const; } // Version 1 Number* Byte::operator +(Byte *in) const { const _byte t = in->data + this->data; if(t < this->data) return new Short(((short) this->data) + in->data); else return new Byte(t); } // Version 2 Number operator +(Byte &in) const { Number res; const _byte t = in.data + this->data; if(t < this->data) res = Short(((short) this->data) + in.data); else res = Byte(t); return res; }So, folgendes verursacht natürlich ein Leak
Byte *n1, *n2, *n3, *res; n1 = new Byte(4); n2 = new Byte(6); n3 = new Byte(5); res = n1 + n2 + n3; // Eine Byte-Instanz geht hier verloren, welche ist nicht definiert. // ---------------------------- Byte b1(5); Byte b1(6); Byte b1(5); Byte res = b1 + b2 + b3; // Keine Leaks, aber alles auf dem Stack!Meine Frage hierzu.
- Gibt es Richtlinien, Empfehlungen,... wann new eingesetzt werden soll?
- In Version 2 wird das Ergebnis im Operator erzeugt und eine Kopie hier von zurückgegeben. Somit führt das Programm bei zwei arithmetischen Aktionen drei überflüssige Kopien durch. In wie weit ist das sinnvoll bzw. optimiert das der Compiler entsprechend?2.) Der C++0x Draft und Rvalue
class Byte { Byte(Byte&& v) { this->data = v.data; v.data = NULL; } // msdn.blog Byte& operator= (Byte&& v) { this->data = v.data; v.data = NULL; return *this;} virtual Number&& operator +(Byte &&in) const; } // Version 3 Number&& operator +(Byte &&in) const { Number &&res; // Geht das, oder verliere ich res nach Methoden ende? const _byte t = in.data + this->data; if(t < this->data) res = Short(((short) this->data) + in.data); else res = Byte(t); return res; }Behebt diese Sprachneuerung das Problem? Oder hab ich da was falsch verstanden?
Byte b1(5); Byte b1(6); Byte b1(5); Byte res = b1 + b2 + b3; // Keine zusätzlichen Kopien Byte *hb = new Byte(res); // Verschiebe res in den Heap // Ab hier dürfte ich res nicht mehr verwenden, // da ich sonst eine Kopie erzeugen muss. Byte *hb2 = new Byte(*hb); // Wenn ich jetzt das richtig // verstehe, muss ich hb löschen bzw. mind. den Destruktor // aufrufen. delete hb; // Oder eben // hb->~Byte(); // hb = new (hb) Byte(16);Besitzt das Objekt eine move und copy Konstruktor. Woher weiß der Compiler, welchen er nehmen soll? Wie kann man das festlegen?
In den folgenden Beiträgen wird die Handhabung von rvalue unterschiedliche Beschreiben. Im ersten Beitrag wird std::move() verwendet und der msdn.blog verzichtet darauf. Ist die Verwendung eher guter Sil (man sieht was geschiet) oder hat sich die Spezifikation in diesem Zeitraum geändert?
Ich frage deswegen, da ich beim GCC 4.4.1 kein std::move finde.
GCC 4.4.1 mit -std=c++0xAchja, wann werden die Unicode string literals beim GCC umgesetzt? Gibt es Alternativen?
Gruß,
Thomas
-
Siassei schrieb:
res = n1 + n2 + n3;Zeiger können nicht zueinander addiert werden, das ist also schlicht ill-formed.
Im Allgemeinen sind bei Operatorüberladung vollständige Objekte involviert und es werden ggf. neue Objekte zurückgegeben. Das ist mit Polymorphie mittels abstrakter Basisklassen nicht vereinbar.Number &&res; // Geht das, oder verliere ich res nach Methoden ende?Res ist immer noch eine Referenz und kein Objekt und muss sofort initialisiert werden.
Siassei schrieb:
Besitzt das Objekt eine move und copy Konstruktor. Woher weiß der Compiler, welchen er nehmen soll?
Durch Überladungauflösung. Eine modifizierbare lvalue-Referenz bindet nur an modifizierbare lvalues. rvalue-Referenzen binden nur an rvalues. lvalue-Referenzen auf const binden an lvalues oder rvalues - ist das Argument allerdings nicht konstant, ist eine Qualifikationskonvertierung notwendig, so dass diese Variante schlechter ist, falls nicht-const Alternativen zur Verfügung stehen. Der Mechanismus ist der gleiche, der heute benutzt wird, um const- und nicht-const-Überladungen zu unterscheiden.