C++ `enable_shared_from_this` 有什么用处?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/712279/
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
What is the usefulness of `enable_shared_from_this`?
提问by fido
I ran across enable_shared_from_this
while reading the Boost.Asio examples and after reading the documentation I am still lost for how this should correctly be used. Can someone please give me an example and/or and explanation of when using this class makes sense.
我在enable_shared_from_this
阅读 Boost.Asio 示例时遇到了问题,在阅读文档后,我仍然不知道如何正确使用它。有人可以给我一个例子和/或解释什么时候使用这个类是有意义的。
回答by 1800 INFORMATION
It enables you to get a valid shared_ptr
instance to this
, when all you have is this
. Without it, you would have no way of getting a shared_ptr
to this
, unless you already had one as a member. This example from the boost documentation for enable_shared_from_this:
它使你得到一个有效的shared_ptr
实例this
,当你已经是this
。没有它,您将无法获得shared_ptr
to this
,除非您已经拥有一个成员。这个例子来自enable_shared_from_this的boost 文档:
class Y: public enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_from_this();
}
}
int main()
{
shared_ptr<Y> p(new Y);
shared_ptr<Y> q = p->f();
assert(p == q);
assert(!(p < q || q < p)); // p and q must share ownership
}
The method f()
returns a valid shared_ptr
, even though it had no member instance. Note that you cannot simply do this:
该方法f()
返回一个有效的shared_ptr
,即使它没有成员实例。请注意,您不能简单地这样做:
class Y: public enable_shared_from_this<Y>
{
public:
shared_ptr<Y> f()
{
return shared_ptr<Y>(this);
}
}
The shared pointer that this returned will have a different reference count from the "proper" one, and one of them will end up losing and holding a dangling reference when the object is deleted.
此返回的共享指针将具有与“正确”引用计数不同的引用计数,并且其中之一将在删除对象时最终丢失并持有悬空引用。
enable_shared_from_this
has become part of C++ 11 standard. You can also get it from there as well as from boost.
enable_shared_from_this
已成为 C++ 11 标准的一部分。您也可以从那里以及从 boost 获取它。
回答by Artashes Aghajanyan
from Dr Dobbs article on weak pointers, I think this example is easier to understand (source: http://drdobbs.com/cpp/184402026):
从 Dobbs 博士关于弱指针的文章中,我认为这个例子更容易理解(来源:http: //drdobbs.com/cpp/184402026):
...code like this won't work correctly:
...这样的代码将无法正常工作:
int *ip = new int;
shared_ptr<int> sp1(ip);
shared_ptr<int> sp2(ip);
Neither of the two shared_ptr
objects knows about the other, so both will try to release the resource when they are destroyed. That usually leads to problems.
这两个shared_ptr
对象都不知道对方,所以当它们被销毁时,它们都会尝试释放资源。这通常会导致问题。
Similarly, if a member function needs a shared_ptr
object that owns the object that it's being called on, it can't just create an object on the fly:
类似地,如果一个成员函数需要一个shared_ptr
拥有它被调用的对象的对象,它不能只是动态地创建一个对象:
struct S
{
shared_ptr<S> dangerous()
{
return shared_ptr<S>(this); // don't do this!
}
};
int main()
{
shared_ptr<S> sp1(new S);
shared_ptr<S> sp2 = sp1->dangerous();
return 0;
}
This code has the same problem as the earlier example, although in a more subtle form. When it is constructed, the shared_pt
r object sp1
owns the newly allocated resource. The code inside the member function S::dangerous
doesn't know about that shared_ptr
object, so the shared_ptr
object that it returns is distinct from sp1
. Copying the new shared_ptr
object to sp2
doesn't help; when sp2
goes out of scope, it will release the resource, and when sp1
goes out of scope, it will release the resource again.
此代码与前面的示例存在相同的问题,但形式更微妙。当它被构造时,shared_pt
r 对象sp1
拥有新分配的资源。成员函数内部的代码S::dangerous
不知道该shared_ptr
对象,因此shared_ptr
它返回的对象与sp1
. 将新shared_ptr
对象复制到sp2
没有帮助;当sp2
超出范围时,它会释放资源,当sp1
超出范围时,它会再次释放资源。
The way to avoid this problem is to use the class template enable_shared_from_this
. The template takes one template type argument, which is the name of the class that defines the managed resource. That class must, in turn, be derived publicly from the template; like this:
避免这个问题的方法是使用类模板enable_shared_from_this
。模板采用一个模板类型参数,即定义托管资源的类的名称。反过来,该类必须从模板公开派生;像这样:
struct S : enable_shared_from_this<S>
{
shared_ptr<S> not_dangerous()
{
return shared_from_this();
}
};
int main()
{
shared_ptr<S> sp1(new S);
shared_ptr<S> sp2 = sp1->not_dangerous();
return 0;
}
When you do this, keep in mind that the object on which you call shared_from_this
must be owned by a shared_ptr
object. This won't work:
执行此操作时,请记住,您调用的对象shared_from_this
必须归某个shared_ptr
对象所有。这行不通:
int main()
{
S *p = new S;
shared_ptr<S> sp2 = p->not_dangerous(); // don't do this
}
回答by mackenir
Here's my explanation, from a nuts and bolts perspective (top answer didn't 'click' with me). *Note that this is the result of investigating the source for shared_ptr and enable_shared_from_this that comes with Visual Studio 2012. Perhaps other compilers implement enable_shared_from_this differently...*
这是我的解释,从细节和螺栓的角度来看(最佳答案没有与我“点击”)。*请注意,这是对 Visual Studio 2012 附带的 shared_ptr 和 enable_shared_from_this 源进行调查的结果。也许其他编译器以不同的方式实现 enable_shared_from_this...*
enable_shared_from_this<T>
adds a private weak_ptr<T>
instance to T
which holds the 'one true reference count' for the instance of T
.
enable_shared_from_this<T>
添加一个私有weak_ptr<T>
实例,T
其中包含 的实例的“一个真实引用计数” T
。
So, when you first create a shared_ptr<T>
onto a new T*, that T*'s internal weak_ptr gets initialized with a refcount of 1. The new shared_ptr
basically backs onto this weak_ptr
.
因此,当您第一次shared_ptr<T>
在新的 T* 上创建 a 时,该 T* 的内部 weak_ptr 将使用 1 的引用计数进行初始化。 newshared_ptr
基本上支持 this weak_ptr
。
T
can then, in its methods, call shared_from_this
to obtain an instance of shared_ptr<T>
that backs onto the same internally stored reference count. This way, you always have one place where T*
's ref-count is stored rather than having multiple shared_ptr
instances that don't know about each other, and each think they are the shared_ptr
that is in charge of ref-counting T
and deleting it when their ref-count reaches zero.
T
然后可以在其方法中调用shared_from_this
以获取一个实例,shared_ptr<T>
该实例返回到相同的内部存储引用计数。这样,您总是有一个地方T*
存储 's ref-count,而不是有多个shared_ptr
彼此不了解的实例,并且每个实例都认为它们shared_ptr
负责 ref-countingT
并在它们的 ref 时删除它-计数达到零。
回答by mchiasson
It's exactly the same in c++11 and later: It is to enable the ability to return this
as a shared pointer since this
gives you a raw pointer.
它在 c++11 及更高版本中完全相同:它是为了能够this
作为共享指针返回,因为this
它为您提供了一个原始指针。
in other word, it allows you to turn code like this
换句话说,它允许你像这样转换代码
class Node {
public:
Node* getParent const() {
if (m_parent) {
return m_parent;
} else {
return this;
}
}
private:
Node * m_parent = nullptr;
};
into this:
进入这个:
class Node : std::enable_shared_from_this<Node> {
public:
std::shared_ptr<Node> getParent const() {
std::shared_ptr<Node> parent = m_parent.lock();
if (parent) {
return parent;
} else {
return shared_from_this();
}
}
private:
std::weak_ptr<Node> m_parent;
};
回答by blais
Note that using a boost::intrusive_ptr does not suffer from this problem. This is often a more convenient way to get around this issue.
请注意,使用 boost::intrusive_ptr 不会遇到此问题。这通常是解决此问题的更方便的方法。
回答by PetrH
Another way is to add a weak_ptr<Y> m_stub
member into the class Y
. Then write:
另一种方法是将weak_ptr<Y> m_stub
成员添加到class Y
. 然后写:
shared_ptr<Y> Y::f()
{
return m_stub.lock();
}
Useful when you cannot change the class you are deriving from (e.g. extending other people's library). Do not forget to initialize the member, e.g. by m_stub = shared_ptr<Y>(this)
, its is valid even during a constructor.
当您无法更改您派生的类时很有用(例如扩展其他人的库)。不要忘记初始化成员,例如 by m_stub = shared_ptr<Y>(this)
,即使在构造函数期间它也是有效的。
It is OK if there are more stubs like this one in inheritance hierarchy, it will not prevent destruction of the object.
如果继承层次结构中有更多这样的存根是可以的,它不会阻止对象的破坏。
Edit:As correctly pointed out by user nobar, the code would destroy Y object when the assignment is finished and temporary variables are destroyed. Therefore my answer is incorrect.
编辑:正如用户 nobar 正确指出的那样,当赋值完成并销毁临时变量时,代码将销毁 Y 对象。所以我的回答是错误的。