Verständnissfrage zum Umgang mit Speicherreservierung
-
Hallo,
wenn ich zwei Methoden habe wobei A, B aufruft:/*Achtung sinnfrei, nur zu Demo.*/ std::vector getData() { std::vector returnValues(10,1); //10 Element mit Wert 1 return returnValues; } void main(...) { do_something_with( getData() ); ... }Wenn ich was (hier std::vector<int>) auf dem Stack allokiere und mit return zurückgebe. Warum kommt das an, es müsste doch eigentlich im Zuge des return freigegeben werden oder wird das kopiert und "gerettet" ?
Meine andere Frage ist Qt-spezifisch aber betrifft auch den Umgang mit dem Speicher:
Wie verhält es sich mit Qt wenn ich einem Widget(hier this) ein Unterwidget (hier QLabel) zuweise wie:new QLabel("foo", this);Dann ist das QLabel in "this" drin aber ich hab keine Referenz drauf. Zerstört das "this" QWidget jetzt dieses Objekt wenn es selbst freigegeben wird oder ist es ne Speicherleiche?
Vielen Dank für konstruktive Antworten!
-
zu 1. Kann schon sein, dass das Objekt noch an dieser Stelle ist, schließlich wird nur der Speicher zur Wiederverwendung freigegeben, aber dabei nicht überschrieben. Die Werte stehen da also noch, aber der Speicher kann jederzeit durch etwas anderes überschrieben werden. Sollte man so also nicht machen.
zu 2. Zu QT kann ich nichts sagen, aber im Regelfall muß zu jedem new ein entsprechendes delete vorhanden sein.
-
die Qt-Klassen sind so aufgebaut, dass das Elternwidget sämtliche Kinder löscht, bevor es selbst gelöscht wird.
Deswegen haben auch alle im Konstruktor einen entsprechenden Zeiger auf das Elternwidget, da dieses dann die Verwaltung dessen übernimmt
-
/*Achtung sinnfrei, nur zu Demo.*/ std::vector getData() { std::vector returnValues(10,1); //10 Element mit Wert 1 return returnValues; } void main(...) { do_something_with( getData() ); ... }Wenn ich was (hier std::vector<int>) auf dem Stack allokiere und mit return zurückgebe. Warum kommt das an, es müsste doch eigentlich im Zuge des return freigegeben werden oder wird das kopiert und "gerettet" ?
Meines Wissens passiert hier folgendes:
getData()-> getData wird aufgerufenstd::vector returnValues(10,1);-> Der entsprechende Konstruktor von vector wird aufgerufen
- Zwischen dem "return" und dem Aufruf von "do_something_with" wird ein temporäres Objekt erstellt, das der Funktion übergeben werden soll
- Von diesem temporären Objekt wird der Kopierkonstruktor aufgerufen, als Paramter "returnValues"
- Von "returnValues" wird der Destruktor aufgerufen, es ist weg
Bei
void do_something_with( const vector<x>& )wird eine Referenz auf das temporäre Objekt übergeben.
Beivoid do_something_with( vector<x>& )müsste es einen Compiler-Fehler geben, weil imo keine nicht-konstante Referenz auf ein temporäres Objekt übergeben werden kann.
Beivoid do_something_with( vector<x> par )würde für par der Kopierkonstruktor aufgerufen werden mit dem temporären Objekt als Argument. Danach wird das temporäre Objekt zerstört, es wird ja nicht mehr gebraucht.Mit Stack-Variablen zu hantieren, ist im Allgemeinen ziemlich sicher, da verschwindet nichts einfach
Du kannst das Verhalten auch testen (ist evtl Compiler-abhängig), indem du eine eigene Klasse deklarierst, diese statt vector verwendest und bei Konstruktor, Kopierkonstruktor und Destruktor entsprechende Nachrichten ausgeben lässt.
-
Hallo,
Badestrand hat dazu schon etwas geschrieben, nur zur Klarstellung noch eine Ergänzung:
Allgemein gesprochen: Bei einer Wertrückgabe bei einer Funktion kann je nach Möglichkeit des Compilers und Komplexität des Ausdruckes einer der zwei folgenden Dinge passieren (genaueres kann dir mit Sicherheit ein Compilerguru sagen ;p):
a) Eine Kopie des Wertes wird angelegt und zurückgegeben
b) Der Compiler optimiert die Kopie weg und es ist effektiv das gleiche ObjektDas wovor du Bedenken hast ist eine Rückgabe per Referenz. Dies sollte man bei lokalen Variablen nicht machen. Den hier wird tatsächlich das Objekt gelöscht (Wobei ich im Hinterkopf habe das es eine Möglichkeit gibt wenn man etwas wie "const typ& variable = Ausdruck()" schreibt, dies vielleicht möglich ist. Da ich aber grundsätzlich Funktionen möglichst narrensicher gestalte, habe ich mich hiermit aber noch nicht beschäftigt, so das ich dies nicht 100%ig sagen kann).
cu André
-
Vielen Dank für die umfassenden Antworten!