经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
智能指针相关:enable_shared_from_this()在开发中的常见应用
来源:cnblogs  作者:哞哞叫的狗  时间:2024/8/19 17:02:24  对本文有异议

类中使用shared_ptr()的问题

当我们先定义一个指针,然后再用这个指针构造两个智能指针

  1. int main()
  2. {
  3. int* pt = new int();
  4. std::shared_ptr<int> p1(pt);
  5. std::shared_ptr<int> p2(pt);
  6. std::cout << "p1.use_count() = " << p1.use_count() << std::endl;
  7. std::cout << "p2.use_count() = " << p2.use_count() << std::endl;
  8. return 0;
  9. }

运行后就会报错,显示的是pt指针被重复释放了
image
原因是p1和p2都以为自己是唯一独占pt的智能指针,不知道还有智能指针指向pt
所以输出后发现两个引用计数都是1

如果需要不报错,就得这样写
shared_ptr<int> p2 = p1
通过p1来定义p2,它们就知道pt有两个智能指针了,就不会报错。

再来看一个代码

  1. class client
  2. {
  3. public:
  4. ~client()
  5. {
  6. std::cout << "~client()\n";
  7. }
  8. };
  9. int main()
  10. {
  11. client* cp = new client();
  12. std::shared_ptr<client> csp1(cp);
  13. std::shared_ptr<client> csp2(cp);
  14. std::cout << "csp1.use_count: " << csp1.use_count() << std::endl;
  15. std::cout << "csp2.use_count: " << csp2.use_count() << std::endl;
  16. return 0;
  17. }

这个报的一样的错,原理相同,问题是我们实际开发中,很多时候需要通过this指针来获取对象的内容
这个时候需要通过enable_shared_from_this来解决问题

enable_shared_from_this的使用

  1. class client : public std::enable_shared_from_this<client>
  2. {
  3. public:
  4. ~client()
  5. {
  6. std::cout << "~client()\n";
  7. }
  8. std::shared_ptr<client> get_ptr()
  9. {
  10. return shared_from_this();
  11. }
  12. };
  13. int main()
  14. {
  15. client* cp = new client();
  16. std::shared_ptr<client> csp1(cp);
  17. std::shared_ptr<client> csp2 = cp->get_ptr();
  18. std::cout << "csp1.use_count: " << csp1.use_count() << std::endl;
  19. std::cout << "csp2.use_count: " << csp2.use_count() << std::endl;
  20. return 0;
  21. }

将代码改写成这样,先公有继承这个模板类。
这里需要注意,在你通过shared_from_this()返回一个类的shared_ptr时,该对象必须已经被一个shared_ptr所管理,所以你不能直接csp2 = cp->get_ptr(),要在此之前先有csp1(cp)
这样的话,借助shared_from_this(),可以使得该对象只要引用计数不为零,就任意获取它的一个shared_ptr。只要还有shared_ptr持有它,它就不会消亡。

实际开发中应用,以一个服务器demo举例

首先看下面一段代码

  1. struct client : std::enable_shared_from_this<client>
  2. {
  3. public:
  4. void start()
  5. {
  6. }
  7. //...其他函数
  8. }
  9. void start()
  10. {
  11. std::shared_ptr<client> s = std::make_shared<client>();
  12. s->start();
  13. }
  14. int main()
  15. {
  16. start();
  17. return 0;
  18. }

这里用make_shared初始化了一个client的shared_ptr,make_shared会让对象和控制块可以安全地存储在连续的内存块中。它简化了内存管理,并提高了性能。但是不支持自己写删除器。
start是一个初始的函数,里面会稍后添加业务,下面我们写一个定时器。

  1. public:
  2. void start()
  3. {
  4. start_up();
  5. }
  6. private:
  7. void start_up()
  8. {
  9. _timer.expires_from_now(std::chrono::seconds(10));
  10. _timer.async_wait(std::bind(&client::time_out, shared_from_this()));
  11. }
  12. void time_out()
  13. {
  14. start_up();
  15. }
  16. private:
  17. boost::asio::steady_timer _timer;

在类里面这样设计定时器,当start()调用的时候,会调用start_up()函数设置一个定时器,并且注册time_out()这个回调函数。
此时start()函数调用结束了,临时变量s的智能指针也已经释放,但是,定时器内通过调用shared_from_this(),返回了一个s管理的对象的shared_ptr给async_wait里的回调time_out()中,s管理的对象并未消亡,直到运行完回调time_out(),它才会消亡,但是回调里面如果继续调用start_up()重新设定计时器,便又会返回一个该对象的shared_ptr()传入新注册的回调time_out()内,以此类推,只要计时器不关闭,永远不会消亡。

基于这一点,可以和读写搭配起来,灵活控制当前类在什么条件下保活,什么条件下析构。

原文链接:https://www.cnblogs.com/wangguangyu12217/p/18367207

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号