webentwicklung-frage-antwort-db.com.de

Ein explizites Löschen eines shared_ptr

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.

18
garsh0p

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_ptrs 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 .

25
Praetorian

[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.

5
Steve Jessop

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.

2
Zan Lynx

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.

1
wulfgarpro

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;
}
0
Nigel Atkinson