Ist dieser Code korrekt?
auto v = make_unique<int>(12);
v.release(); // is this possible?
Entspricht es delete
einem rohen Zeiger?
Antworten:
Nein, der Code verursacht einen Speicherverlust. release
wird 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
detach
wäre viel weniger irreführend als release
.
release
?
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- nullptr
Parameter angegeben std::unique_ptr<>::reset()
).
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_ptr
er 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_ptr
wäre reset()
. Denken Sie jedoch daran, dass diese vorhanden unique_ptr
sind, damit Sie den darin enthaltenen Speicher nicht direkt verwalten müssen. Das heißt, Sie sollten wissen, dass a unique_ptr
den 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.
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, v
es verwaltet nicht mehr die Lebensdauer dieses Zeigers, sondern delegiert den Besitz des Rohzeigers an x
. Wenn Sie nur release
nichts zuweisen, verlieren Sie den Rohzeiger.
.get()
gefolgt .reset()
, um Dinge auszutauschen, aber eigentlich möchte ich .release()
folgen .reset()
, um sicherzustellen, dass der .reset()
Aufruf nicht delete
das alte Objekt ist. .release()
führt dann die gleiche Funktion aus wie .get()
nach dem Loslassen des Zeigers.
.reset()
aber einfache Zuordnung nach .release()
.
.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 get
jetzt ein "baumelnder Zeiger" und der Zugriff darauf ist ein undefiniertes Verhalten.
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.
int* raw
undint *raw
das war das erste Mal, dass ich gesehen habeint * raw