31

这里有一个简单的问题:您是否允许自己显式删除 a boost::shared_ptr?你应该吗?

澄清一下,我并不是说删除shared_ptr. 我的意思是实际shared_ptr本身。我知道大多数人建议不要这样做,所以我只是想知道是否可以明确地这样做。

4

5 回答 5

34

你的问题不清楚。如果您已经shared_ptr动态分配了 a ,那么您当然可以随时使用delete它。

但是,如果您询问是否允许删除 由 管理的任何对象shared_ptr,那么答案是……这取决于。如果shared_ptr::unique返回 true,则调用shared_ptr::reset将删除托管对象。但是,如果shared_ptr::unique返回 false,则表示该对象有多个shared_ptr共享所有权。在这种情况下,调用reset只会导致引用计数减 1,当最后一个shared_ptr管理该对象超出范围或者是它本身时,将发生对象的实际删除reset

编辑:
编辑后,您似乎在询问是否要删除动态分配的shared_ptr. 像这样的东西:

auto sp = new boost::shared_ptr<int>( new int(42) );

// do something with sp

delete sp;

这是允许的,并且会按预期工作,尽管这将是一个不寻常的用例。唯一需要注意的是,如果在分配和删除之间sp创建另一个shared_ptr共享对象所有权的对象,则删除sp不会导致对象被删除,这只会在对象的引用计数变为 0 时发生。

于 2012-09-07T16:33:42.197 回答
6

[编辑:deleteshared_ptr且仅当它是用new, 与任何其他类型一样创建时,您可以。我想不出你为什么要创建一个shared_ptrwith new,但没有什么能阻止你。]

嗯,你可以delete ptr.get();

这样做几乎不可避免地会导致未定义的行为,或者当其他共享所有者使用他们shared_ptr访问现在已删除的对象时,或者该shared_ptr对象的最后一个被销毁,并且该对象再次被删除。

所以不,你不应该。

的目的shared_ptr是管理一个没有任何“人”有权或有责任删除的对象,因为可能有其他人共享所有权。所以你也不应该想要。

于 2012-09-07T16:34:43.917 回答
3

您不能将其引用计数强制为零,不。

想想它需要什么才能起作用。您需要去每个使用 shared_ptr 的地方并清除它。

如果您确实强制删除共享指针并将其设置为 NULL,那么它就像一个weak_ptr。但是,代码中使用 shared_ptr 的所有这些地方都没有为此做好准备,并且期望持有一个有效的指针。他们没有理由检查 NULL,因此这些代码会崩溃。

于 2012-09-07T16:31:54.650 回答
3

如果要模拟计数递减,可以在堆上手动执行,如下所示:

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;
}

或者在堆栈上使用std::shared_ptr::reset()如下:

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;
} 

但它不是那么有用。

于 2017-03-22T06:20:14.763 回答
1

Expliticly deleting comes in handy in some (very?) rare cases.

In addition to explicitly deleting, sometimes you HAVE to explicitly destruct a shared pointer when you are 'deleting' it!

Things can get weird when interfacing with C code, passing a shared_ptr as an opaque value.

For example I have the following for passing objects to and from the Lua scripting language which is written in C. (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 );
}

So thats a shared_ptr in some malloc'd memory. The reverse is this... (setup to be called just before Lua garbage collects an object and 'free's it).

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;
}
于 2017-05-24T00:53:19.643 回答