std::vector push_back() destruktor umgehen
-
Mir fällt es etwas schwer zu verstehen, was eine "leere" Klasse ist, nachdem sie bewegt wurde.
Sie ist nicht leer, sondern ihre Ressourcen wurden weitergegeben. Meistens ist sie dann entweder einfach ungültig, oder ihr Status ist nicht weiter definiert, oder sie ist einfach im "Standardzustand" (also ein Container ist im "Standardzustand" leer, ohne Elemente - welchen Status der Allokator hat, hängt von anderen Sachen ab).
Edit: Hat das doppelte Ampersand (&) eine wirkliche bedeutung oder ist das nur da, um den move zu definieren?
Ja, damit qualifizierst du einen Typen um eine sog. rvalue-Referenz zu bekommen.
int a; // Ein Objekt int& a_ref = a; // Eine lvalue-Referenz auf int int&& a_rref = std::move(a); // eine rvalue-Referenz auf int. Bei Skalaren ist moven sinnlos, da diese keine Ressourcen halten.
-
lvalue und rvalue...
x = 3;x ist lvalue und 3 ist rvalue, richtig?
-
Ja, richtig! 3 ist ein Literal. Ein (normales) Literal ist immer ein rvalue.
Und x muss ein lvalue sein.
-
Haha jaa

Aber ich verstehe nicht den zusammenhang mit Klassen.
Und:
Gibt es einen Unterschied zwischen folgenden Funktionen?:void MyClass::operator=(const MyClass& other){ ... } MyClass& MyClass::operator=(const MyClass& other){ ... return [MyClass]; }Und woher weiß der Compiler, welchen operator= ich meine?
-
void MyClass::operator=(const MyClass& other) // Sollte wohl MyClass& zurückgeben { ... } MyClass& MyClass::operator=(const MyClass& other) { ... return [MyClass]; // Was ist das? Du meinst wohl *this... }Und woher weiß der Compiler, welchen operator= ich meine?
Du darfst so gar nicht überladen. Funktionen, die sich nur ihn ihrem Rückgabewert unterscheiden, können nicht überladen werden.
-
- schrieb:
void MyClass::operator=(const MyClass& other) // Sollte wohl MyClass& zurückgeben { ... } MyClass& MyClass::operator=(const MyClass& other) { ... return [MyClass]; // Was ist das? Du meinst wohl *this... }Und woher weiß der Compiler, welchen operator= ich meine?
Du darfst so gar nicht überladen. Funktionen, die sich nur ihn ihrem Rückgabewert unterscheiden, können nicht überladen werden.
Also sind beide Funktionen identisch?
[MyClass] sollte ein platzhalter für ein objekt vom typ MyClass sein...Edit: Wieso ruft das den CopyCtor auf?
MyClass m4(std::move(m2));
-
Weil kein Move-Konstruktor definiert ist.
-
kralo9 schrieb:
knivil schrieb:
Nun, ob MyClass wirklich ein ReferenceCounter ist, bezweifle ich. Die is_a-Beziehung kann schwer gerechtfertigt werden.
Da gebe ich dir Recht. Es sollte eine Has-A Beziehung sein. Ansonsten gebe ich dir kein Recht.
Has-A löst auch das Problem mit der Namensreservierung der Funktionen.
Du könntest den relativ seltenen Weg der privaten Vererbung wählen. Die drückt eine "is implemented by"-Beziehung aus. Und da du ja nicht per Basisklassenzeiger oder -referenz auf deine Objekte zugreifst brauchst du in Richtung ReferenceCounter auch keine Polymorphie haben.
Dann:
void MyClass::operator=(const MyClass& other) { // ... } MyClass& MyClass::operator=(const MyClass& other) { return *this; }Die void Methode ist nicht sehr sinnvoll, denn dadurch werden solche Konstrukte nicht mehr möglich sein:
MyClass m1, m2, m3; m1 = m2 = m3 = MyClass(); if ( (m1 = 2*m2) == m3 ) {}Zweitens gibt es das wunderschnöde Copy&Swap Pattern:
MyClass::MyClass(MyClass const& m) { // Copy-C-Tor Implementieren } MyClass& MyClass::operator=(MyClass m) { this->swap(m); return *this; } void MyClass::swap(MyClass & other) { // swap implementieren }
-
Ich glaube die has-a Beziehung ist ganz ok. Danke dennoch für das Erwähnen der is-implemented-by beziehung.
Ich möchte nochmal die Frage stellen, ob std::move(m123) den Destruktor von m123 aufruft.
Ich zähl nochmal kurz auf:
Ctor
CopyCtor
operator=
MoveCtor
Move-operator=
(Swap-operator=)Gibt es noch was?
Neue Objekte, d.h. eine Erhöhung des Counters, entsteht nur bei den ersten 3 Möglichkeiten, richtig?
-
Nein, das ist falsch.
Neue Objekte werden bei allen 3 Konstruktoren erzeugt: Ctor,Copy-Ctor, Move-Ctor.
Die Assignment-Operatoren löschen zwar alte Ressourcen, aber erzeugen keine neuen Objekte.
Und die Swap-Methode ist eine normale Methode. Infos
Move ruft keinen Destruktor auf. Move ruft den Move Konstruktor oder Zuweisungsoperator auf. Da weisst du dann, dass du das übergebene Objekt in einen Zustand bringen kannst, der nicht mehr interessiert, da es eh nicht gebraucht wird. (Das stimmt so natürlich nicht, jedes lebendige Objekt sollte immer in einem gültigen Zustand sein. Vielleicht wäre Initial- oder Leerzustand treffender.)