Shared_ptr删除对象
shared_ptr deletes the object
void ClassName::LocalMethod( )
{
boost::shared_ptr<ClassName> classNamePtr( this );
//some operation with classNamePtr
return;
}
在这里,对象从LocalMethod()返回时被释放,因为classNamePtr超出了作用域。难道shared_ptr不够聪明,知道ClassName对象仍然在作用域中,而不是删除它吗?
为对象创建shared_ptr
意味着什么?这意味着shared_ptr
的持有人现在对该对象具有所有权。所有权意味着对象将在他希望删除时被删除。当shared_ptr
的持有者销毁其shared_ptr
时,假设该对象没有其他shared_ptr
,这将导致该对象潜在地被销毁。
当shared_ptr
是类的成员时,这意味着shared_ptr
所指向的对象的生命周期至少与shared_ptr
所指向的对象的生命周期相同。当shared_ptr
在堆栈上时,这意味着shared_ptr
指向的对象的生命周期至少与创建它的作用域一样长。对象一旦从栈上掉下来,就可以被删除。
唯一的时间你应该把一个指针包装到一个shared_ptr
是当你分配对象最初。为什么?因为对象不知道它是否在shared_ptr
中。它不可能知道。这意味着创建原始shared_ptr
的人现在有责任将其传递给需要共享该内存所有权的其他人。共享所有权工作的唯一方式是通过shared_ptr
的复制构造函数。例如:
shared_ptr<int> p1 = new int(12);
shared_ptr<int> p2 = p1.get();
shared_ptr<int> p3 = p1;
shared_ptr
的复制构造函数在p1
和p3
之间创建共享所有权。注意p2
不与p1
共享所有权。它们都认为自己拥有相同内存的所有权,但这与共享内存是不一样的。因为他们都认为他们有独特的所有权
因此,当三个指针被销毁时,将发生以下情况。首先,p3
将被破坏。但由于p3和p1共享整数的所有权,整数还不会被销毁。接下来,p2
将被破坏。因为它认为自己是该整数的唯一持有者,所以它将销毁该整数。
此时,p1
指向已删除的内存。当p1
被销毁时,它认为它是该整数的唯一持有者,因此它将销毁它。是坏的,因为它已经被销毁了。
shared_ptr
。但你只有this
,这是一个常规指针。你是怎么做的?你将得到一些建议enable_shared_from_this
的例子。但是考虑一个更相关的问题:"为什么这些函数将shared_ptr
作为参数?"
函数接受的指针类型表明该函数对其实参做什么。如果一个函数接受shared_ptr
类型,这意味着它需要拥有指针。它需要共享内存的所有权。因此,查看代码并询问这些函数是否真的需要来获得内存的所有权。他们是否将shared_ptr
长期存储在某个地方(即:在对象中),或者他们只是在函数调用期间使用它们?
如果是后者,那么函数应该使用裸指针,而不是shared_ptr
。这样,它们就不能声明所有权。你的接口是自文档化的:指针类型解释了所有权。
然而,有可能你调用的函数确实需要共享所有权。然后你需要使用enable_shared_from_this
。首先,您的类需要从enable_shared_from_this
派生。然后,在函数中:
void ClassName::LocalMethod()
{
boost::shared_ptr<ClassName> classNamePtr(shared_from_this());
//some operation with classNamePtr
return;
}
注意这里是有代价的。enable_shared_from_this
在类中放置一个boost::weak_ptr
。但是没有虚拟开销或类似的东西;它不会使类成为虚的。enable_shared_from_this
是一个模板,所以你必须像这样声明它:
class ClassName : public boost::enable_shared_from_this<ClassName>
难道shared_ptr不够聪明,不能知道ClassName对象是还在范围内,不删除吗?
这不是shared_ptr
的工作原理。当您在构造shared_ptr
时传递指针时,shared_ptr
将承担对指针(在本例中为*this
)的所有权。换句话说,由于shared_ptr
现在拥有该指针,因此shared_ptr
假定对该指针的整个生命周期具有完全的控制权。因此,最后一个拥有该指针的shared_ptr
将删除它。
如果ClassName::LocalMethod()
之外没有classNamePtr
的副本,可以传递一个在构造classNamePtr
时不做任何事情的delete。下面是一个使用自定义删除器来防止shared_ptr
删除其指针的示例。使示例适应您的情况:
struct null_deleter // Does nothing
{
void operator()(void const*) const {}
};
void ClassName::LocalMethod()
{
// Construct a shared_ptr to this, but make it so that it doesn't
// delete the pointee.
boost::shared_ptr<ClassName> classNamePtr(this, null_deleter());
// Some operation with classNamePtr
// The only shared_ptr here will go away as the stack unwinds,
// but because of the null deleter it won't delete this.
return;
}
也可以使用enable_shared_from_this
从this
中获取shared_ptr
。注意,成员函数shared_from_this()
只有在现有的shared_ptr
已经指向this
的情况下才有效。
class ClassName : public enable_shared_from_this<ClassName>
{
public:
void LocalMethod()
{
boost::shared_ptr<ClassName> classNamePtr = shared_from_this();
}
}
// ...
// This must have been declared somewhere...
shared_ptr<ClassName> p(new ClassName);
// before you call this:
p->LocalMethod();
这是一个更合适的,"官方"的方法,它比null delete方法要少得多。
也可能是您实际上不需要首先创建shared_ptr
。//some operation with classNamePtr
注释部分包含什么内容?也许还有比前两种方法更好的方法
- 线程调用的函数对对象删除是否安全?
- 当我使用dynamic_cast并删除对象删除时,析构函数是如何工作的?
- 使用 com 对象删除计划任务
- C 将对象删除为参考
- C样式对象删除的包装器
- 静态映射中动态分配的对象.删除必要的
- C++指向对象删除的指针数组,"Debug assertion failure!"
- 在其成员函数返回之前,将对象删除是不确定的行为吗?
- Python 对象删除检测
- C++安全对象删除
- Qt:RemoveWidget和对象删除
- Qt对象删除导致崩溃
- 删除由两个shared_pointer实例管理的对象(删除其中一个)
- 顶点缓冲区对象(删除进程)opengl
- 设计 -- 按名称或对象删除
- 提升中的异常:进程间,共享内存对象删除
- 使用std::function和std::bind来存储回调并处理对象删除
- 如何使用智能指针防止双重对象删除
- 指针指向对象删除时自动为空
- 对象层次结构中的对象删除责任