Speicher freigeben, durch aufeinanderfolgende Zeiger
-
Ich hab mir jetzt deinen Link zu single und shared ownership angesehen.
Also wenn ich das richtig verstanden habe, wird bei einem unique_ptr der Speicher freigegeben, sobald er zerstört wird.
Bei einem shared_ptr erst, wenn ALLE Referenzen zerstört werden.Also könnte ich doch mit mehreren Instanzen den gleichen Speicherbereich addressieren, sodass dieser erst freigegeben wird, sobald alle Instanzen zerstört werden, oder?
Haltet ihr es generell sinvoll einen unique_ptr zu verwenden, anstatt eines standardmäßigen Zeigers? So muss man nicht daran denken, den Speicher selbst freizugeben und beugt so Speicherlücken(kann man so verlorenen Speicher bezeichnen?) vor.
Einfacher ist es natürlich, Zeiger möglichst wenig zu verwenden und wenn dann vorsichtig mit ihnen umgehen, aber es steigert ja außerdem die Lesbarkeit und verhindert "Speichermüll".
-
coder++ schrieb:
Haltet ihr es generell sinvoll einen unique_ptr zu verwenden, anstatt eines standardmäßigen Zeigers? So muss man nicht daran denken, den Speicher selbst freizugeben und beugt so Speicherlücken(kann man so verlorenen Speicher bezeichnen?) vor.
In modernem C++ sind "besitzende" rohe Zeiger verpönt. Es ist also keine schlechte Idee unique_ptr zu verwenden.
-
MichelRT schrieb:
coder++ schrieb:
Haltet ihr es generell sinvoll einen unique_ptr zu verwenden, anstatt eines standardmäßigen Zeigers? So muss man nicht daran denken, den Speicher selbst freizugeben und beugt so Speicherlücken(kann man so verlorenen Speicher bezeichnen?) vor.
In modernem C++ sind "besitzende" rohe Zeiger verpönt. Es ist also keine schlechte Idee unique_ptr zu verwenden.
Okay, danke.
Irgendwie hab ich das nie wirklich mitgekriegt, dass rohe Zeiger nicht mehr in modernes C++ gehören.
-
coder++ schrieb:
Okay, danke.
Irgendwie hab ich das nie wirklich mitgekriegt, dass rohe Zeiger nicht mehr in modernes C++ gehören.Doch schon, aber sie sollen eben nur zeigen und nichts anderes.
Wenn man einen Besitz und damit die Pflicht zur Speicherfreigabe ausdruecken will, verwendet man soweit moeglich unique_ptr. Wenn es mehr als einen Besitzer gibt, sollte man erstmal sein Design ueberdenken und dann ggf. shared_ptr verwenden. shared_ptr schuetzt auch nicht in allen Situationen, z.B. bei zyklischen Abhaengigkeiten geht das nicht, die sollte man aber so gut wie nie haben.
Nebenbei gilt noch, dass man fuer pointer auf Arrays ( int ptr = new int[10];* ) kein unique_ptr, sondern Container nehmen sollte.
-
Marthog schrieb:
coder++ schrieb:
Okay, danke.
Irgendwie hab ich das nie wirklich mitgekriegt, dass rohe Zeiger nicht mehr in modernes C++ gehören.Doch schon, aber sie sollen eben nur zeigen und nichts anderes.
Wenn man einen Besitz und damit die Pflicht zur Speicherfreigabe ausdruecken will, verwendet man soweit moeglich unique_ptr. Wenn es mehr als einen Besitzer gibt, sollte man erstmal sein Design ueberdenken und dann ggf. shared_ptr verwenden. shared_ptr schuetzt auch nicht in allen Situationen, z.B. bei zyklischen Abhaengigkeiten geht das nicht, die sollte man aber so gut wie nie haben.
Nebenbei gilt noch, dass man fuer pointer auf Arrays ( int ptr = new int[10];* ) kein unique_ptr, sondern Container nehmen sollte.Achso. Ich dachte mit rohen Zeigern sind schon nur die Zeiger gemeint, welche Speicher angefordert haben.
Und für Arrays benutze ich meistens sowieso vector und je nach dem auch map aus der Standardbibliothek.
-
coder++ schrieb:
Irgendwie hab ich das nie wirklich mitgekriegt, dass rohe Zeiger nicht mehr in modernes C++ gehören.
Das entscheidende ist der Zusatz "besizende" rohe Zeiger.
Als Parameter für Funktionen/Methoden sind Zeiger natürlich nach wie vor erlaubt.
Tabu ist natürlich das Speicher(also in Besitz nehmen) des so übergebenen Zeigers über die Lebenszeit der Funktion/Methode.
-
Ich wollte mal fragen, ob folgendes Minimal-Beispiel funktioniert, bzw. ob der Speicher erst nach löschen der Addressen aus beiden shared_ptren freigegeben wird.
boost::shared_ptr<int> sp1(new int); boost::shared_ptr<int> sp2; sp2.reset(sp1.get()); // Es wird die Addresse, nicht der shared_ptr übergeben sp1.reset(); std::cout << *sp2; /* "Weiß" sp1, dass sp2 existiert und hat den Speicher nicht freigegeben, oder eben nicht, wodurch der Speicher freigegeben und vielleicht schon neu belegt wurde? */ sp2.reset();In diesem Beispiel geht es mir darum, ob ich den shared_ptr kopieren muss, oder ob es schon reicht die gleiche Addresse zu laden, da get() ja die wirkliche Addresse zurückgibt.
-
Das löscht zwei mal.
-
manni66 schrieb:
Das löscht zwei mal.
Der Speicher wird beides mal freigegeben?
Was hab ich falsch gemacht?
-
Du musst
boost::shared_ptr<int> sp2; sp2.reset(sp1.get()); // Es wird die Addresse, nicht der shared_ptr übergebendurch
boost::shared_ptr<int> sp2 = sp1;ersetzen. Andernfalls zeigen beide shared_ptr auf den gleichen Wert, wissen aber nicht von dem anderen und meinen dass sie die einzigen sind. Beide versuchen beim Ableben den Wert freizugeben, beim zweiten kracht es.
Wenn du die die Zeiger direkt kopierst dann zeigen beide auf den gleichen Wert, wissen indirekt von dem anderen Zeiger und nur der letzte gibt frei.
-
Ethon schrieb:
Du musst
boost::shared_ptr<int> sp2; sp2.reset(sp1.get()); // Es wird die Addresse, nicht der shared_ptr übergebendurch
boost::shared_ptr<int> sp2 = sp1;ersetzen. Andernfalls zeigen beide shared_ptr auf den gleichen Wert, wissen aber nicht von dem anderen und meinen dass sie die einzigen sind. Beide versuchen beim Ableben den Wert freizugeben, beim zweiten kracht es.
Wenn du die die Zeiger direkt kopierst dann zeigen beide auf den gleichen Wert, wissen indirekt von dem anderen Zeiger und nur der letzte gibt frei.
Danke.
Also ist reset() ja eigentlich nur dafür da, neuen Speicher anzufordern.
-
Jap. Zb so:
shared_ptr<int> sp(new int); sp.reset(new int); // Kein Leak
-
Ethon schrieb:
Jap. Zb so:
shared_ptr<int> sp(new int); sp.reset(new int); // Kein LeakOkay.