Einfache Frage hier: Können Sie ein boost::shared_ptr
selbst explizit löschen? Solltest du jemals
Klar, ich meine nicht den Zeiger, der vom shared_ptr
gehalten wird. Ich meinte das eigentliche shared_ptr
selbst. Ich weiß, dass die meisten Leute vorschlagen, es nicht zu tun, also habe ich mich nur gefragt, ob es in Ordnung ist, es explizit zu tun.
Ihre Frage ist nicht klar. Wenn Sie einen shared_ptr
dynamisch zugewiesen haben, können Sie ihn delete
jederzeit verwenden, wenn Sie möchten.
Wenn Sie jedoch fragen, ob Sie das Objekt löschen dürfen, das von shared_ptr
verwaltet wird, lautet die Antwort ... es hängt davon ab. Wenn shared_ptr::unique
true zurückgibt, wird beim Aufrufen von shared_ptr::reset
das verwaltete Objekt gelöscht. Wenn jedoch shared_ptr::unique
false zurückgibt, bedeutet dies, dass mehrere shared_ptr
s das Objekt gemeinsam nutzen. In diesem Fall führt ein Aufruf von reset
nur dazu, dass der Referenzzähler um 1 dekrementiert wird. Das tatsächliche Löschen des Objekts findet statt, wenn der letzte shared_ptr
, der das Objekt verwaltet, entweder den Gültigkeitsbereich verlässt oder selbst reset
ist.
BEARBEITEN:
Nach der Bearbeitung werden Sie anscheinend gefragt, ob Sie einen dynamisch zugewiesenen shared_ptr
löschen möchten. Etwas wie das:
auto sp = new boost::shared_ptr<int>( new int(42) );
// do something with sp
delete sp;
Dies ist zulässig und funktioniert wie erwartet, obwohl dies ein ungewöhnlicher Anwendungsfall wäre. Der einzige Nachteil ist, dass das Löschen von sp
nicht zu einer Löschung des Objekts führt, wenn Sie zwischen der Zuweisung und dem Löschen von sp
einen anderen shared_ptr
erstellen, der den Besitz des Objekts gemeinsam hat .
[Bearbeiten: Sie können delete
einen shared_ptr
wenn und nur dann, wenn sie mit new
erstellt wurde, genau wie bei jedem anderen Typ. Ich kann mir nicht vorstellen, warum Sie einen shared_ptr
mit new
erstellen, aber es gibt nichts, was Sie daran hindert.]
Nun, Sie könnten schreiben delete ptr.get();
.
Dies führt fast zwangsläufig zu undefiniertem Verhalten: Entweder verwenden die gemeinsam genutzten other - Besitzer ihren shared_ptr
für den Zugriff auf das jetzt gelöschte Objekt oder der letzte shared_ptr
des Objekts wird zerstört, und das Objekt wird erneut gelöscht.
Nein, das solltest du nicht.
Der Zweck von shared_ptr
besteht darin, ein Objekt zu verwalten, für das keine "Person" das Recht oder die Verantwortung zum Löschen hat, da möglicherweise andere Personen das Eigentum teilen. Sie sollten es also auch niemals tun.
Sie können den Referenzzähler nicht auf Null setzen, nein.
Überlegen Sie, was dafür nötig wäre. Sie müssen an jeden Ort gehen, an dem das shared_ptr verwendet wird, und es löschen.
Wenn Sie den gemeinsamen Zeiger zwingen, zu löschen, und ihn auf NULL setzen, entspricht dies einem schwachen_ptr. Allerdings sind all diese Stellen im Code, die diesen shared_ptr verwenden, nicht dafür bereit und erwarten einen gültigen Zeiger. Sie haben keinen Grund, nach NULL zu suchen, und daher würden diese Codebits abstürzen.
Wenn Sie den Countdown-Wert simulieren möchten, können Sie dies manuell auf dem Heap tun:
int main(void) {
std::shared_ptr<std::string>* sp = new std::shared_ptr<std::string>(std::make_shared<std::string>(std::string("test")));
std::shared_ptr<std::string>* sp2 = new std::shared_ptr<std::string>(*sp);
delete sp;
std::cout << *(*sp2) << std::endl; // test
return 0;
}
Oder auf dem Stack mit std::shared_ptr::reset()
wie folgt:
int main(void) {
std::shared_ptr<std::string> p = std::make_shared<std::string>(std::string("test"));
std::shared_ptr<std::string> p2 = p;
p.reset();
std::cout << *p2 << std::endl; // test
return 0;
}
Aber es ist nicht so nützlich.
Explizites Löschen ist in einigen (sehr?) Seltenen Fällen hilfreich.
Zusätzlich zum expliziten Löschen MÜSSEN Sie manchmal einen gemeinsamen Zeiger explizit zerstören, wenn Sie ihn löschen.
Bei der Verwendung von C-Code kann es merkwürdig werden, dass ein shared_ptr als undurchsichtiger Wert übergeben wird.
Zum Beispiel habe ich Folgendes, um Objekte an und von der Lua-Skriptsprache zu übergeben, die in C geschrieben ist. (Www.lua.org)
static void Push( lua_State *L, std::shared_ptr<T> sp )
{
if( sp == nullptr ) {
lua_pushnil( L );
return;
}
// This is basically malloc from C++ point of view.
void *ud = lua_newuserdata( L, sizeof(std::shared_ptr<T>));
// Copy constructor, bumps ref count.
new(ud) std::shared_ptr<T>( sp );
luaL_setmetatable( L, B::class_name );
}
Das ist also ein shared_ptr in irgendeinem malloc'd Speicher. Das Gegenteil ist das ... (Setup, das aufgerufen werden soll, bevor Lua Müll ein Objekt sammelt und es frei gibt).
static int destroy( lua_State *L )
{
// Grab opaque pointer
void* ud = luaL_checkudata( L, 1, B::class_name );
std::shared_ptr<T> *sp = static_cast<std::shared_ptr<T>*>(ud);
// Explicitly called, as this was 'placement new'd
// Decrements the ref count
sp->~shared_ptr();
return 0;
}