明确删除shared_ptr

时间:2012-09-07 16:23:41

标签: c++ boost shared-ptr boost-smart-ptr

这里的简单问题:您是否可以自己明确删除boost::shared_ptr?你应该吗?

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

5 个答案:

答案 0 :(得分:25)

你的问题不明确。如果您已动态分配了shared_ptr,则无论何时您都可以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时发生。

答案 1 :(得分:5)

[修改:当且仅当delete创建shared_ptr时,您可new shared_ptr,与任何其他类型相同。我想不出你为什么用new创建一个delete ptr.get();,但没有什么能阻止你。]

好吧,你可以shared_ptr

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

所以不,你不应该。

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

答案 2 :(得分:3)

你不能强迫它的引用计数为零,不能。

考虑一下这项工作需要什么。你需要去每个地方使用shared_ptr并清除它。

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

答案 3 :(得分:1)

如果要模拟计数减量,可以在堆上手动执行:

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

但它并没有那么有用。

答案 4 :(得分:0)

在某些(非常?)极少数情况下,删除很方便。

除了明确删除之外,有时你必须在删除&#39;时明确地破坏共享指针。它!

在与C代码连接时,将shared_ptr作为不透明值传递可能会变得奇怪。

例如,我有以下内容用于将对象传递给用C语言编写的Lua脚本语言。(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 );
}

这就是某些malloc内存中的shared_ptr。反过来就是这样......(在Lua垃圾收集对象之前调用的设置和“免费”)。

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