我一直在尝试了解从enable_shared_from_this
继承的有用性,尽管在那里对该机制的工作做了一些解释。我在那个post上找不到此问题的答案,所以我在这里发布。
在其中一个示例中。下面的示例是一个不好的做法。我知道两个共享指针互不认识的原因,一旦其中一个共享指针超出范围,资源将被破坏。
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;
}
我的问题是为什么用户不这样做
shared_ptr<S> sp2 = sp1;
那还不只是增加参考数量吗?会好吗?是否出于某些原因给出了该示例,以防该类无法访问sp1并需要返回一个shared_ptr
?
答案 0 :(得分:2)
核心问题在这里,由于某种原因,并非代码中的每个共享指针都对其余的代码“已知”。
如果您可以访问已给定的shared_ptr
,则应始终按照编写时的使用shared_ptr<S> sp2 = sp1;
。与使用std::enable_shared_from_this
相比,这绝对是更好的选择。
让我们举一个例子:
struct S: std::enable_shared_from_this<S>
{
std::shared_ptr<S> getPtr() { return shared_from_this(); }
};
// Here we have no interface for providing a shared_ptr, maybe
// code that we can't change or maintain or comes as callback from
// a library we want to use
void f( S* s )
{
// here we have no access to shared_ptr<S>...
// so we need to have access to the unique counting instance
// of all other shared_ptr which are pointing to this object
std::shared_ptr<S> p3 = s->getPtr();
std::cout << p3.use_count() << std::endl;
// do some stuff....
}
int main()
{
std::shared_ptr<S> p1 = std::make_shared<S>();
std::cout << p1.use_count() << std::endl;
// This example is useless, as you can directly use p1
std::shared_ptr<S> p2 = p1->getPtr();
std::cout << p1.use_count() << std::endl;
std::cout << p2.use_count() << std::endl;
// But if we have to use a interface, which is not providing access via shared_ptr like this:
f(p1.get());
}
这里要解决的关键问题仅仅是访问公共的“句柄”,该句柄将我们系统IF中的所有其他shared_ptr连接起来!我们根本无法访问任何shared_ptr!
我们无法访问对象中任何现有的shared_ptr的原因可能很多,例如:使用旧的接口,该接口只允许使用原始指针,但我们希望在其他代码中使用回调来使用共享的ptr来自也仅支持原始指针等的库。
使用std::enable_shared_from_this<S>
有一些缺点:
您的接口不再可以使用const S*
,因为创建新的shared_ptr
将修改std::enable_shared_from_this
的数据,该数据现在是您的类或结构的基类。还会增加对象的大小。