C++ 显式删除 shared_ptr

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12321949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:09:29  来源:igfitidea点击:

Explicitly deleting a shared_ptr

c++boostshared-ptrboost-smart-ptr

提问by meteoritepanama

Simple question here: are you allowed to explicitly delete a boost::shared_ptryourself? Should you ever?

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

Clarifying, I don't mean delete the pointer held by the shared_ptr. I meant the actual shared_ptritself. I know most people suggest to not do it, so I was just wondering if it's OK to explicitly do it.

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

回答by Praetorian

Your question isn't clear. If you've allocated a shared_ptrdynamically then you're certainly allowed to deleteit whenever you want.

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

But if you're asking whether you're allowed to delete whatever object is being managed by the shared_ptr, then the answer is ... it depends. If shared_ptr::uniquereturns true, then calling shared_ptr::resetwill delete the managed object. However, if shared_ptr::uniquereturns false, it means there are more than one shared_ptrs sharing ownership of that object. In this case a call to resetwill only result in the reference count being decremented by 1, actual deletion of the object will take place when the last shared_ptrmanaging that object either goes out of scope or is itself reset.

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

EDIT:
After your edit, it seems you are asking about deleting a dynamically allocated shared_ptr. Something like this:

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

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

// do something with sp

delete sp;

This is allowed and will work as expected, although it would be an unusual use case. The only caveat is that if in between the allocation and deletion of spyou create another shared_ptrthat shares ownership of the object, deleting spwill not result in deletion of the object, that will only happen when the reference count for the object goes to 0.

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

回答by Steve Jessop

[Edit: you can deletea shared_ptrif and only if it was created with new, same as any other type. I can't think why you'd create a shared_ptrwith new, but there's nothing stopping you.]

[编辑:你可以delete一个shared_ptr当且仅当它与创造new,与任何其他类型。我想不通你为什么要创建shared_ptrwith new,但没有什么能阻止你。]

Well, you couldwrite delete ptr.get();.

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

Doing so leads almost inevitably to undefined behavior either when the othershared owners use their shared_ptrto access the now-deleted object, or the last shared_ptrto the object is destroyed, and the object gets deleted again.

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

So no, you shouldn't.

所以不,你不应该。

The purpose of shared_ptris to manage an object that no one "person" has the right or responsibility to delete, because there could be others sharing ownership. So you shouldn't ever want to, either.

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

回答by wulfgarpro

If you want to simulate the count decrement, you can do it manually on the heap like so:

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

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

Or on the stack using std::shared_ptr::reset()like so:

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

But it's not that useful.

但它不是那么有用。

回答by Zan Lynx

You cannot force its reference count to zero, no.

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

Think about what would be required for that to work. You would need to go to each place the shared_ptr is used and clear it.

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

If you did force the shared pointer to delete and set it to NULL, it would be just like a weak_ptr. However, all those places in the code using that shared_ptr are not ready for that and expect to be holding a valid pointer. They have no reason to check for NULL, and so those bits of code would crash.

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

回答by Nigel Atkinson

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.

与 C 代码交互时,事情会变得很奇怪,将 shared_ptr 作为不透明值传递。

For example I have the following for passing objects to and from the Lua scripting language which is written in C. (www.lua.org)

例如,我有以下用于将对象传入和传出用 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 );
}

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

所以这就是某些 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;
}