C++ QtList append, macht es ein copy ?

Speedrat

Lieutenant
Registriert
Nov. 2006
Beiträge
590
Moin zusammen,

ich spiele aktuell ein wenig mit Qt rum und da ich in der letzten Zeit zu Java geschädigt bin, habe ich folgendes gemacht:

Code:
QtList<myClass> list;

int main() {
   do_something();
   //ab hier
}

void do_something() {
  myClass temp;
  temp.var = 5;
  list.append(tmp)
}

Ich gebe append also eine Referenz auf eine lokales Objekt, welches sich ja auf den Stack befindet und somit nach den aufruf von do_something wieder frei gegeben wird.
Ich habe es aber nachgestellt das selbst nach den Freigaben des Stacks und erneutes befüllen durch weitere aufrufe anderer Funktionen, mein tmp weiterhin erfolgreich in der Liste bleibt. Doch wieso ? kopiert das append das Opjekt erst ?
 
Hmm vermutlich allokiert die Funktion append Speicher aufm Heap, tmp ist dann solange da bis list das objekt oder den Speicher mittels delete freigibt. Bei C++ muss man sich um die Speicherverwaltung selbst kümmern, alles was du mit new erzeugst landet im Heap und bleibt auch dort bis du es mit delete entfernst.
 
Joa soweit bin ich mir bewusst, auch das mein Code oben eigentlich Grob Fahrlässig ist was das angeht, aber irgendwie tut es doch und das erspart mir die arbeit mich selber um den Speicher zu kümmern (an der Stelle).
Ich würde gerne wisse das genau er da macht. (aus den Source von append sieht man das nicht mal eben so auf der schnelle ;-) )
 
Joa das ist eigentlich ganz einfach, es handelt sich dabei um eine verkette Liste. QList "kopiert" letzten Endes die tmp Variable und versieht die mit nem Pointer auf seinen Vorgänger und Nachfolger, wenn tmp der einzige Wert in der Liste ist dann ist zeigt auch noch der "Begin" Pointer auf die neuerstelle tmp in der QList.
 
Es erzeugt ne Kopie von deinem Objekt das in der List gespeicher wird.
Wenn du wirklich dein Objekt speichern willst musst du folgendes machen:

Code:
QtList<myClass*> list;

void do_something() {
  myClass* temp = new myClass();
  temp->var = 5;
  list.append(tmp)
}

Du musst dann aber auch später das Objekt manuell wieder freigeben (mit delete) nachdem du es aus der Liste genommen hast.
 
Ich denke auch dass beim Einfügen eine Kopie erstellt wird. Hab in der Doku beim überfliegen nichts gefunden, ist aber auch bei STL-Containern so.
Ansonsten könntest du ja von außen die Elemente der Liste manipulieren, ohne auf direkt auf die Liste zuzugreifen.
 
Logisch macht's eine Kopie. Schau dir mal die Signatur der Methode an:

void QList::append ( const T & value )

Die Methode erwartet also eine const-Referenz auf ein Objekt. Von hier aus kann man dann logisch auf 2 Möglichkeiten schließen:

a) Die append()-Methode speichert tatsächlich nur eine const-Referenz (eigentlich einen const-Pointer, da Container von Referenzen ein Ding der Unmöglichkeit sind) in der Liste. Das wär aber blöd, da die Liste keine Kontrolle darüber hat, wie lange das Objekt, auf das der gespeicherte Pointer eigentlich zeigt, überhaupt existiert. In einem Beispiel würde das referenzierte temp-Objekt beim Verlassen von do_something() schon wieder aufhören, zu existieren. Die Liste enthielte dann also einen Pointer, der quasi nur noch auf Schrott zeigt.

b) Die append()-Methode nutzt die übergebene const-Referenz, um eine Kopie des Arguments anzulegen und die in der Liste zu speichern.

Da a) Mist ist, bleibt ja eigentlich nur b).
 
Er legt auf jeden Fall eine Kopie an, was man sich aber auch selbst hätte erschließen können in dem man den von antred in a) beschriebenen Fall testet...

Es wird halt eine Const by Reference genutzt um 1. zu verhindern das "value" während des Aufrufes von append geändert wird und 2. da in append bestimmt noch Prüfungen stattfinden werden eine Referenz, damit erst dann eine Kopie erstellt wird wenn diese nicht fehlschlagen.
 
Nur zwecks allgemeiner Verwirrung möchte ich noch anmerken, das es in C++11 noch die Operation Verschieben gibt:
http://en.cppreference.com/w/cpp/utility/move

Das hat dann den Effekt, das ein Objekt in den STL Container verschoben wird. Hat zur Folge, wie man in dem oben verlinkten Beispiel zu sehen ist, dass das lokale Objekt nach dem Verschieben leer ist. Bei der ganzen Aktion wird jedenfalls nicht der Kopierkonstruktor aufgerufen.
Inwieweit die Qt Containerklassen sowas inzwischen unterstützt: keine Ahnung.
Nach Values, Pointern und L-Referenzen in C++98, hat die Welt eindeutig auf R-Referenzen gewartet :freak:
 
So ich halte fest:
Er macht wirklich eine Kopie! (habs auch nochmal nachgestellt ^^)
 
Finde den Code eh nicht gut muss ich zugeben ^^

würde ja eher sowas in die Richtung machen...
Code:
QtList<myClass> list;
 
int main() {
   list.append(do_something());
   //ab hier
}
 
myClass do_something() {
  myClass temp;
  temp.var = 5;
  return temp;
}
 
Zurück
Oben