何时/如何使用 std::enable_shared_from_this<T>?

打印 上一主题 下一主题

主题 974|帖子 974|积分 2922

要点回首


  • 继承自 std::enable_shared_from_this 的类可以或许在其自身实例中通过 std::shared_from_this 方法创建一个指向自己的 std::shared_ptr 智能指针。
  • 从一个裸指针创建多个 std::shared_ptr 实例会造成严峻的后果,其活动是未定义的。
  • std::enable_shared_from_this 现实包含了一个用于指向对象自身的 std::weak_ptr 指针。

引言

本文先容 std::enable_shared_from_this 及 std::shared_from_this 的基本概念和使用方法。


定义 "std::enable_shared_from_this"

以下内容是 cppreference.com 上关于 std::enable_shared_from_this 的定义和分析:
Defined in header < memory >
template< class T > class enable_shared_from_this; (since C++11)
std::enable_shared_from_this allows an object t that is currently managed by a std::shared_ptr named pt to safely generate additional std::shared_ptr instances pt1, pt2, ... that all share ownership of t with pt.
Publicly inheriting from std::enable_shared_from_this provides the type T with a member function shared_from_this. If an object t of type T is managed by a std::shared_ptr named pt, then calling T::shared_from_this will return a new std::shared_ptr that shares ownership of t with pt.
简单来说就是,继承自 std::enable_shared_from_this 的类可以或许在其自身实例中通过 std::shared_from_this 方法创建一个指向自己的 std::shared_ptr 智能指针。
想要理解 std::enable_shared_from_this,起首得知道为什么需要 std::enable_shared_from_this,请看下文。

使用 "std::enable_shared_from_this"

为什么需要 std::enable_shared_from_this? 我们从一个例子讲起,会更轻易一些。
假定有一个类 Processor, 它的作用是异步处理数据并且存储到数据库。当 Processor 吸收到数据时,它通过一个定制的 Executor 范例来异步处理数据:
  1. class Executor {
  2. public:
  3. //Executes a task asynchronously
  4. void
  5. execute(const std::function<void(void)>& task);
  6. //....
  7. private:
  8. /* Contains threads and a task queue */
  9. };
  10. class Processor {
  11. public:
  12. //...
  13. //Processes data asynchronously. (implemented later)
  14. void processData(const std::string& data);
  15. private:
  16. //Called in an Executor thread
  17. void doProcessAndSave(const std::string& data) {
  18.     //1. Process data
  19.     //2. Save data to DB
  20. }
  21. //.. more fields including a DB handle..
  22. Executor* executor;
  23. };
复制代码
Client 类包含了一个 std::shared_ptr 实例,Processor 从 Client 类吸收数据:
  1. class Client {
  2. public:
  3. void someMethod() {
  4.   //...
  5.   processor->processData("Some Data");
  6.   //..do something else
  7. }
  8. private:
  9. std::shared_ptr<Processor> processor;
  10. };
复制代码
以上示例中,Executor 是一个线程池,用于执行任务队列中的任务。
在 Processor::processData 中,我们需要通报一个(指针)函数(lambda 函数)给 Executor 来执行异步操作。该 lambda 函数调用 Processor::doProcessAndSave 以完成现实的数据处理工作。因此,该 lambda 函数需要捕捉一个 Processor 对象的引用/指针。我们可以如许做:
  1. void Processor::processData(const std::string& data) {
  2. executor->execute([this, data]() { //<--Bad Idea
  3.    //Executes in an Executor thread asynchronously
  4.    //'this' could be invalid here.
  5.    doProcessAndSave(data);
  6. });
  7. }
复制代码
self = shared_from_this() 通报的是一个正当的 std::shared_ptr 实例,正当的类 Processor 对象的引用。

深入 "std::enable_shared_from_this" 内部

std::enable_shared_from_this 的实现雷同:
  1. void good() {
  2. auto p{new int(10)}; //p is int*
  3. std::shared_ptr<int> sp1{p};
  4. //Create additional shared_ptr from an existing shared_ptr
  5. auto sp2{sp1}; //OK. sp2 shares control block with sp1
  6. }
复制代码
enable_shared_from_this 包含了一个 std::weak_ptr 指针,这正是函数 shared_from_this 返回的内容。注意,为什么不是 std::shared_ptr? 因为对象包含自身的计数引用会导致对象永远不被释放,从而发生内存泄漏。上述代码中 weak_this 会在类对象被 std::shared_ptr 引用时赋值,也就是std::shared_ptr 实例的构造函数中赋值,这也是为什么类 enable_shared_from_this 的最后,其被声明成为了 shared_ptr 的友元。

总结

到此,关于 std::enable_shared_from_this 的先容就竣事了。

引用

https://en.cppreference.com/w/cpp/memory/enable_shared_from_this
https://www.nextptr.com/tutorial/ta1414193955/enable_shared_from_this-overview-examples-and-internals

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表