这里的简单问题:您是否可以自己明确删除boost::shared_ptr
?你应该吗?
澄清,我不是指删除shared_ptr
所持的指针。我的意思是实际shared_ptr
本身。我知道大多数人建议不要这样做,所以我只是想知道是否可以明确地做到这一点。
答案 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;
}