Ruft unique_ptr :: release () den Destruktor auf?


74

Ist dieser Code korrekt?

auto v =  make_unique<int>(12);
v.release();     // is this possible?

Entspricht es deleteeinem rohen Zeiger?

Antworten:


159

Nein, der Code verursacht einen Speicherverlust. releasewird verwendet, um den Besitz des verwalteten Objekts freizugeben, ohne es zu löschen:

auto v = make_unique<int>(12);  // manages the object
int * raw = v.release();        // pointer to no-longer-managed object
delete raw;                     // needs manual deletion

Tun Sie dies nur, wenn Sie einen guten Grund haben, den Rohspeicher ohne Sicherheitsnetz zu jonglieren.

Verwenden Sie zum Löschen des Objekts reset.

auto v = make_unique<int>(12);  // manages the object
v.reset();                      // delete the object, leaving v empty

9
Ich habe gesehen, wie Leute geschrieben haben, int* rawund int *rawdas war das erste Mal, dass ich gesehen habeint * raw
Cory Kramer

13
@Cyber: Es ist Geschmackssache. Ich betrachte das Zeigerqualifikationsmerkmal nicht als "angehängt" an den Typ oder die Variable, daher hänge ich es auch nicht an.
Mike Seymour

12
Wenn es traurig ist, dass sie sich entschieden haben, diese Funktionsnamen zu verwenden. So etwas detachwäre viel weniger irreführend als release.
Minexew

1
@eepp Würde das das Objekt zerstören oder einfach nur mögen release?
Tuket

1
Ich bin nicht einverstanden @nenchev. Ich denke , Zuordnung von nullptr ist mehr klar. Es gibt buchstäblich nichts anderes, als das Objekt zu löschen, auf das verwiesen wird (es ist unique_ptr), da es offensichtlich den aktuellen Wert durch nullptr ersetzt. Für reset () müssen Sie die Dokumente lesen, um genau zu wissen, was diese Funktion tut.
MadScientist

28

Ist dieser Code korrekt?

Nein. Verwenden Sie std::unique_ptr<>::reset()diese Option, um den internen Rohzeiger zu löschen:

auto v =  std::make_unique<int>(12);
v.reset(); // deletes the raw pointer

Danach std::unique_ptr<>::get()wird zurückgegeben nullptr(es sei denn, Sie haben einen Nicht- nullptrParameter angegeben std::unique_ptr<>::reset()).


20

Ist dieser Code korrekt?

Es ist nicht und wird auslaufen.

release()Lassen Sie den aufrufenden Code einfach den Besitz des Speichers zurückerobern, den unique_ptrer bis zum Aufruf gespeichert hat . Wenn Sie den von zurückgegebenen Zeiger nicht zuweisen release(), liegt nur ein Leck vor.

Ein explizites Löschen für a unique_ptrwäre reset(). Denken Sie jedoch daran, dass diese vorhanden unique_ptrsind, damit Sie den darin enthaltenen Speicher nicht direkt verwalten müssen. Das heißt, Sie sollten wissen, dass a unique_ptrden zugrunde liegenden Rohzeiger sicher löscht, sobald er den Gültigkeitsbereich verlässt.

Sie sollten also einen sehr guten Grund haben, eine manuelle Speicherverwaltung für ein automatisches Speicherverwaltungsobjekt durchzuführen.


12

release wird Ihren rohen Zeiger verlieren, da Sie ihn nichts zuweisen.

Es soll für so etwas wie verwendet werden

int* x = v.release();

Das heißt, ves verwaltet nicht mehr die Lebensdauer dieses Zeigers, sondern delegiert den Besitz des Rohzeigers an x. Wenn Sie nur releasenichts zuweisen, verlieren Sie den Rohzeiger.


Ah ich sehe. In meinem Code habe ich also .get()gefolgt .reset(), um Dinge auszutauschen, aber eigentlich möchte ich .release()folgen .reset(), um sicherzustellen, dass der .reset()Aufruf nicht deletedas alte Objekt ist. .release()führt dann die gleiche Funktion aus wie .get()nach dem Loslassen des Zeigers.
Andrew

oder vielleicht nicht, .reset()aber einfache Zuordnung nach .release().
Andrew

Ein .get()gefolgt von einem .reset()wird ein Problem verursachen. Das .get()gibt Ihnen einen nicht besitzenden Zeiger und .reset()ruft dann auf delete, daher ist Ihr Rohzeiger von getjetzt ein "baumelnder Zeiger" und der Zugriff darauf ist ein undefiniertes Verhalten.
Cory Kramer

2

Für beliebige Typen kann es etwas schwierig sein:

  unique_ptr<Foo> v = get_me_some_foo();  // manages the object
  Foo * raw = v.release();        // pointer to no-longer-managed object
  delete raw;

ist fast richtig.

  unique_ptr<Foo> v = get_me_some_foo();  // manages the object
  Foo * ptr = v.release();        // pointer to no-longer-managed object
  v.get_deleter() ( ptr );

dieser wäre in jeder Situation richtig; Möglicherweise ist ein benutzerdefinierter Deleter für den Typ Foo definiert, aber die Verwendung des vom unique_ptr-Objekt zurückgegebenen Deleters ist in allen Fällen sinnvoll.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.