(7条消息) C++11新特性之十:enable

enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为:

template< class T > class enable_shared_from_this;

std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。
       若一个类 T 继承 std::enable_shared_from_this<T> ,则会为该类 T 提供成员函数: shared_from_this 。 当 T 类型对象 t 被一个为名为 pt 的 std::shared_ptr<T> 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr<T> 对象,它与 pt 共享 t 的所有权。

一.使用场合

当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr。

1.为何不直接传递this指针

使用智能指针的初衷就是为了方便资源管理,如果在某些地方使用智能指针,某些地方使用原始指针,很容易破坏智能指针的语义,从而产生各种错误。

2.可以直接传递share_ptr<this>么?

答案是不能,因为这样会造成2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次。例如:

  1. #include <memory>
  2. #include <iostream>
  3. class Bad
  4. {
  5. public:
  6. std::shared_ptr<Bad> getptr() {
  7. return std::shared_ptr<Bad>(this);
  8. }
  9. ~Bad() { std::cout << "Bad::~Bad() called" << std::endl; }
  10. };
  11. int main()
  12. {
  13. // 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者
  14. std::shared_ptr<Bad> bp1(new Bad());
  15. std::shared_ptr<Bad> bp2 = bp1->getptr();
  16. // 打印bp1和bp2的引用计数
  17. std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl;
  18. std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl;
  19. } // Bad 对象将会被删除两次

输出结果如下:


当然,一个对象被删除两次会导致崩溃。

正确的实现如下:

  1. #include <memory>
  2. #include <iostream>
  3. struct Good : std::enable_shared_from_this<Good> // 注意:继承
  4. {
  5. public:
  6. std::shared_ptr<Good> getptr() {
  7. return shared_from_this();
  8. }
  9. ~Good() { std::cout << "Good::~Good() called" << std::endl; }
  10. };
  11. int main()
  12. {
  13. // 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构
  14. {
  15. std::shared_ptr<Good> gp1(new Good());
  16. std::shared_ptr<Good> gp2 = gp1->getptr();
  17. // 打印gp1和gp2的引用计数
  18. std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl;
  19. std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl;
  20. }
  21. system("pause");
  22. }

输出结果如下:

二.为何会出现这种使用场合

       因为在异步调用中,存在一个保活机制,异步函数执行的时间点我们是无法确定的,然而异步函数可能会使用到异步调用之前就存在的变量。为了保证该变量在异步函数执期间一直有效,我们可以传递一个指向自身的share_ptr给异步函数,这样在异步函数执行期间share_ptr所管理的对象就不会析构,所使用的变量也会一直有效了(保活)。

具体的应用可以参考:Boost.Asio C++ 网络编程之五:TCP回显服务端/客户端

(0)

相关推荐

  • C 11中智能指针的原理、使用、实现

    目录 理解智能指针的原理 智能指针的使用 智能指针的设计和实现 1.智能指针的作用 C 程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理.程序员自己管理堆内存可以提高了程序的 ...

  •  C++11中shared

    在C++中,动态内存的管理是通过一对运算符来完成的:new,在动态内存中为对象分配空间并返回一个指向该对象的指针,可以选择对对象进行初始化:delete,接受一个动态对象的指针,销毁该对象,并释放与之 ...

  • 现代C一文读懂智能指针

    https://m.toutiao.com/is/JHS4MVf/ 智能指针 C++11 引入了 3 个智能指针类型: std::unique_ptr<T> :独占资源所有权的指针. st ...

  • c 11新特性之智能指针

    很多人谈到c++,说它特别难,可能有一部分就是因为c++的内存管理吧,不像java那样有虚拟机动态的管理内存,在程序运行过程中可能就会出现内存泄漏,然而这种问题其实都可以通过c++11引入的智能指针来 ...

  • (7条消息) C++11 std::bind std::function 高级用法

    从最基础的了解,std::bind和std::function /* * File: main.cpp * Author: Vicky.H * Email: eclipser@163.com */ # ...

  • (3条消息) C++11/14/17

    目录 环境准备 被弃用的特性 常量字符串赋值需要使用const char* 与C的兼容性 语言可用性的强化 类型推导 区间迭代 列表初始化 模板增强 面对对象增强 语言运行期的强化 Lambda表达式 ...

  • iPhone 11 新变化,十二年来首次

    果粉俱乐部 让科技更好的服务生活 点击上方「蓝字」加入我们 苹果将在本周三凌晨举行今年的秋季新品发布会,这是苹果一年当中最重要的一天,年度旗舰 iPhone 在接连不断的传闻之后,终于要揭开神秘的面纱 ...

  • (1条消息) 苹果手机各种尺寸详细表以及iPhoneX、iPhoneXS、iPhoneXR、iPhoneXSMax、iPhone 11、iPhone 12、屏幕适配

    iPhone设备物理分辨率是硬件所支持的,逻辑分辨率是软件可以达到的.代数设备操作系统逻辑分辨率(point)物理分辨率(pixel)屏幕尺寸(对角线长度)缩放因子iPhone第一代iPhone 2G ...

  • (7条消息) Ubuntu16.04系统中创建新用户

    转载:https://blog.csdn.net/timothy93bp/article/details/77679000 本文基于Linux的Ubuntu系统新建一个普通用户,linux系统的用户名 ...

  • 中国创造新的世界纪录!这条消息,看不懂你也会点赞

    "一团耀眼的白光从山脉尽头升起--"在科幻小说<三体>中,太空飞船核聚变发动机发出的光芒如同太阳.用核聚变等技术,人类走出家园,成为真正的太空文明. 来源:@小央视频 ...

  • UC头条:本月开工! 山西这条高铁传来新消息!

    据山西省投资项目监管审批平台消息,太中银铁路太原南至柳林南段开行动车组列车工程计划本月开工. 点击加载图片 太原南至柳林南段开行动车组列车由太原南站引出,经山西省太原市.晋中市.清徐县.交城县.文水县 ...

  • 厉害了!广州11条在建地铁传来新进展!你最期待哪条新线开通?

    马上就要过年啦 春节期间,广州地铁运营时间 也有部分调整 大家出行前一定要注意啦 春节广州地铁运营时间调整 根据春运期间乘客出行特点及方便市民节日出行,广州地铁将分三个时间段延长线网运营服务时间: 2 ...