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指向同一个对象,未增加引用计数导对象被析构两次。例如:

#include <memory>
#include <iostream>
 
class Bad
{
public:
    std::shared_ptr<Bad> getptr() {
        return std::shared_ptr<Bad>(this);
    }
    ~Bad() { std::cout << "Bad::~Bad() called" << std::endl; }
};
 
int main()
{
    // 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者
    std::shared_ptr<Bad> bp1(new Bad());
    std::shared_ptr<Bad> bp2 = bp1->getptr();
    // 打印bp1和bp2的引用计数
    std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl;
    std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl;
}  // Bad 对象将会被删除两次
输出结果如下:

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

正确的实现如下:

#include <memory>
#include <iostream>
 
struct Good : std::enable_shared_from_this<Good> // 注意:继承
{
public:
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
    ~Good() { std::cout << "Good::~Good() called" << std::endl; }
};
 
int main()
{
    // 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构
    {
        std::shared_ptr<Good> gp1(new Good());
        std::shared_ptr<Good> gp2 = gp1->getptr();
        // 打印gp1和gp2的引用计数
        std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl;
        std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl;
    }
    system("pause");
}
输出结果如下:

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

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

具体的应用可以参考:Boost.Asio C++ 网络编程之五:TCP回显服务端/客户端
————————————————
版权声明:本文为CSDN博主「草上爬」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/caoshangpa/article/details/79392878

C++11新特性:enable_shared_from_this的更多相关文章

  1. C++ 11学习和掌握 ——《深入理解C++ 11:C++11新特性解析和应用》读书笔记(一)

    因为偶然的机会,在图书馆看到<深入理解C++ 11:C++11新特性解析和应用>这本书,大致扫下,受益匪浅,就果断借出来,对于其中的部分内容进行详读并亲自编程测试相关代码,也就有了整理写出 ...

  2. C++11新特性总结 (二)

    1. 范围for语句 C++11 引入了一种更为简单的for语句,这种for语句可以很方便的遍历容器或其他序列的所有元素 vector<int> vec = {1,2,3,4,5,6}; ...

  3. C++11新特性总结 (一)

    1. 概述 最近在看C++ Primer5 刚好看到一半,总结一下C++11里面确实加了很多新东西,如果没有任何了解,别说自己写了,看别人写的代码估计都会有些吃力.C++ Primer5是学习C++1 ...

  4. C++ 11 新特性

    C++11新特性:          1.auto          2.nullptr          3.for          4.lambda表达式          5.override ...

  5. [转载] C++11新特性

    C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...

  6. 在C++98基础上学习C++11新特性

    自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...

  7. C++11新特性——range for

    很多编程语言都有range for语法功能,自C++11起,终于将这个重要功能加入C++标准中.range for语句,可以方便的遍历给定序列中的每个元素并对其执行某种操作. 1.基本语法 for(d ...

  8. C++11新特性——大括号初始化

    C++11之前,C++主要有以下几种初始化方式: //小括号初始化 string str("hello"); //等号初始化 string str="hello" ...

  9. C++11新特性之六——元编程

    C++11新特性之六——元编程

  10. C++11新特性之一——Lambda表达式

    C++11新特性总结可以参考:http://www.cnblogs.com/pzhfei/archive/2013/03/02/CPP_new_feature.html#section_6.8 C++ ...

随机推荐

  1. 8.2 k8s 基于StatefulSet运行mysql 一主多从 ,数据通过pv/pvc结合NFS服务器持久化

    1.准备mysql和xtrabackup镜像 下载mysql官方镜像并上传到本地harbor docker pull mysql:5.7 docker tag m ysql:5.7 192.168.1 ...

  2. 【samtools】运行报错: error while loading shared libraries:libcrypto.so.1.0.0或libncurses.so.5或libtinfow.so.5

    samtools用conda安装后,总是出现共享库缺失的报错.即便你刚安装samtools时可以用,但后面在同一环境中安装其他相关软件,有可能产生了冲突,导致库替换,因而报错. 避免这种情况,可能最好 ...

  3. 15.Pow(x, n)

    Pow(x, n) Total Accepted: 88351 Total Submissions: 317095 Difficulty: Medium Implement pow(x, n). 思路 ...

  4. 避免UE4项目VS中误改源码.h文件导致编译时间长

    最近几天两次触发VS中误改UE4源码头文件,导致需要编译大量源码的情况:再好的习惯也有不可靠的时候,还是需要可靠方案解决这个问题:官方提供了预编译版本(即从Launcher中下载的版本),但是对于程序 ...

  5. mybatis项目中,使用useSSL=true却报错

    今天在玩儿mybatis的时候遇到一个蛮有东西的事情:抛了一个让我折腾几个小时的错误,所以记录一下 这个错误有意思的地方就在于这里: 当使用useSSL安全连接时,抛出了上述的错误把useSSL改为f ...

  6. 一文搞懂指标采集利器 Telegraf

    作者| 姜闻名 来源|尔达 Erda 公众号 ​ 导读:为了让大家更好的了解 MSP 中 APM 系统的设计实现,我们决定编写一个<详聊微服务观测>系列文章,深入 APM 系统的产品.架构 ...

  7. acute

    In Euclidean geometry, an angle is the figure formed by two rays, called the sides of the angle, sha ...

  8. 【leetcode】153. Find Minimum in Rotated Sorted Array

    Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example ...

  9. Linux基础命令---get获取ftp文件

    get 使用lftp登录ftp服务器之后,可以使用get指令从服务器获取文件.   1.语法       get [-E]  [-a]  [-c] [-O base]  rfile  [-o lfil ...

  10. Synchronized深度解析

    概览: 简介:作用.地位.不控制并发的影响 用法:对象锁和类锁 多线程访问同步方法的7种情况 性质:可重入.不可中断 原理:加解锁原理.可重入原理.可见性原理 缺陷:效率低.不够灵活.无法预判是否成功 ...