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
Explicitly deleting a shared_ptr
提问by meteoritepanama
Simple question here: are you allowed to explicitly delete a boost::shared_ptr
yourself? Should you ever?
这里有一个简单的问题:您是否可以明确删除boost::shared_ptr
自己?你应该吗?
Clarifying, I don't mean delete the pointer held by the shared_ptr
. I meant the actual shared_ptr
itself. 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_ptr
dynamically then you're certainly allowed to delete
it 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::unique
returns true, then calling shared_ptr::reset
will delete the managed object. However, if shared_ptr::unique
returns false, it means there are more than one shared_ptr
s sharing ownership of that object. In this case a call to reset
will only result in the reference count being decremented by 1, actual deletion of the object will take place when the last shared_ptr
managing 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 sp
you create another shared_ptr
that shares ownership of the object, deleting sp
will 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 delete
a shared_ptr
if and only if it was created with new
, same as any other type. I can't think why you'd create a shared_ptr
with new
, but there's nothing stopping you.]
[编辑:你可以delete
一个shared_ptr
当且仅当它与创造new
,与任何其他类型。我想不通你为什么要创建shared_ptr
with 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_ptr
to access the now-deleted object, or the last shared_ptr
to the object is destroyed, and the object gets deleted again.
这样做几乎不可避免地会导致未定义的行为,无论是当其他共享所有者使用它们shared_ptr
来访问现在删除的对象时,还是对象的最后一个shared_ptr
被销毁,并且对象再次被删除。
So no, you shouldn't.
所以不,你不应该。
The purpose of shared_ptr
is 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;
}