shared_ptr 删除对象
void ClassName::LocalMethod( )
{
boost::shared_ptr<ClassName> classNamePtr( this );
//some operation with classNamePtr
return;
}
这里,当对象从 LocalMethod() 返回时,它会被释放,因为 classNamePtr 超出了范围。难道shared_ptr不够聪明,知道ClassName对象仍在范围内而不删除它吗?
void ClassName::LocalMethod( )
{
boost::shared_ptr<ClassName> classNamePtr( this );
//some operation with classNamePtr
return;
}
Here the object is getting released when it returns from LocalMethod() since classNamePtr is out of scope. Isn't the shared_ptr smart enough to know that the ClassName object is still in scope and not to delete it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为对象创建
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
的复制构造函数在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
派生。然后,在函数中:注意,这里有一个成本。
enable_shared_from_this
在类中放置一个boost::weak_ptr
。但没有虚拟开销或类似的东西;它不会使课堂变得虚拟。enable_shared_from_this
是一个模板,因此您必须像这样声明它:What does it mean to create a
shared_ptr
to an object? It means that the holder of theshared_ptr
now assumes ownership over the object. Ownership meaning that the object will be deleted when he so desires. When the holder of theshared_ptr
destroys itsshared_ptr
, that will cause the object to potentially be destroyed, assuming that there are no othershared_ptr
s to that object.When a
shared_ptr
is a member of a class, that means that the lifetime of the object pointed to by theshared_ptr
is at least as long as the object that theshared_ptr
is a member of. When ashared_ptr
is on the stack, this means that the lifetime of the object that theshared_ptr
is pointing to will be at least as long as the scope it was created in. Once the object falls off the stack, it may be deleted.The only time you should ever take a pointer and wrap it into a
shared_ptr
is when you are allocating the object initially. Why? Because an object does not know whether it is in ashared_ptr
or not. It can't know. This means that the person who creates the originalshared_ptr
now has the responsibility to pass it around to other people who need to share ownership of that memory. The only way shared ownership works is through the copy constructor ofshared_ptr
. For example:The copy constructor of
shared_ptr
creates shared ownership betweenp1
andp3
. Note thatp2
does not share ownership withp1
. They both think they have ownership over the same memory, but that's not the same as sharing it. Because they both think that they have unique ownership of it.Therefore, when the three pointers are destroyed, the following will happen. First,
p3
will be destroyed. But since p3 and p1 share ownership of the integer, the integer will not be destroyed yet. Next,p2
will be destroyed. Since it thinks that it is the only holder of the integer, it will then destroy it.At this point,
p1
is pointing to deleted memory. Whenp1
is destroyed, it thinks that it is the only holder of the integer, so it will then destroy it. This is bad, since it was already destroyed.Your problem is this. You are inside an instance of a class. And you need to call some functions of yours that take a
shared_ptr
. But all you have isthis
, which is a regular pointer. What do you do?You're going to get some examples that suggest
enable_shared_from_this
. But consider a more relevant question: "why do those functions take ashared_ptr
as an argument?"The type of pointer a function takes is indicative of what that function does with its argument. If a function takes a
shared_ptr
, that means that it needs to own the pointer. It needs to take shared ownership of the memory. So, look at your code and ask whether those functions truly need to take ownership of the memory. Are they storing theshared_ptr
somewhere long-term (ie: in an object), or are they just using them for the duration of the function call?If it's the latter, then the functions should take a naked pointer, not a
shared_ptr
. That way, they cannot claim ownership. Your interface is then self-documenting: the pointer type explains ownership.However, it is possible that you could be calling functions that truly do need to take shared ownership. Then you need to use
enable_shared_from_this
. First, your class needs to be derived fromenable_shared_from_this
. Then, in the function:Note that there is a cost here.
enable_shared_from_this
puts aboost::weak_ptr
in the class. But there is no virtual overhead or somesuch; it doesn't make the class virtual.enable_shared_from_this
is a template, so you have to declare it like this:这不是
shared_ptr
的工作原理。当您在构造shared_ptr
时传递指针时,shared_ptr
将取得指针对象的所有权(在本例中为*this< /代码>)。换句话说,由于
shared_ptr
现在拥有指针对象,因此shared_ptr
承担了对指针对象生命周期的完全控制。因此,最后一个拥有该指针的shared_ptr
将删除它。如果
ClassName::LocalMethod()
之外没有classNamePtr
的副本,您可以传递一个在构造时不执行任何操作的删除器>classNamePtr
。 下面是一个用于防止 < code>shared_ptr 删除其指针对象。根据您的情况调整示例:您还可以使用
enable_shared_from_this
从this
获取shared_ptr
。请注意,成员函数shared_from_this()
仅当现有shared_ptr
已指向this
时才起作用。这是更合适的“官方”方法,并且比空删除器方法要简单得多。
也可能您实际上并不需要首先创建
shared_ptr
。//some operation with classNamePtr
注释部分包含哪些内容?可能还有比前两种方法更好的方法。That's not how
shared_ptr
works. When you pass a pointer while constructing ashared_ptr
, theshared_ptr
will assume ownership of the pointee (in this case,*this
). In other words, theshared_ptr
assumes total control over the lifetime of the pointee by virtue of the fact that theshared_ptr
now owns it. Because of this, the lastshared_ptr
owning the pointee will delete it.If there will be no copies of
classNamePtr
outside ofClassName::LocalMethod()
, you can pass a deleter that does nothing while constructingclassNamePtr
. Here's an example of a custom deleter being used to prevent ashared_ptr
from deleting its pointee. Adapting the example to your situation:You can also use
enable_shared_from_this
to obtain ashared_ptr
fromthis
. Note that the member functionshared_from_this()
only works if you have an existingshared_ptr
already pointing tothis
.This is the more appropriate, "official" method and it's much less hackish than the null deleter method.
It could also be that you don't actually need to create a
shared_ptr
in the first place. What goes into the section commented//some operation with classNamePtr
? There might be an even better way than the first two ways.