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");
}
输出结果如下:

该技术实现了从原指针获取shared_ptr

————————————————
版权声明:本文为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. 痞子衡嵌入式:深扒IAR启动函数流程之段初始化实现中可用的压缩选项

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是IAR启动函数流程里段初始化实现中可用的压缩选项. 接着 <IAR启动函数流程之段初始化函数__iar_data_init3实现& ...

  2. DotNetty实现WebSocket的简单使用

    工作中项目是物联网项目的,管理平台又是bs架构. 如果用 Socket 的话,Web 端还需要转发,就全部统一采用了 WebSocket . DotNet 平台上的 WebSocket 实现有很多种, ...

  3. URL URI傻傻分不清楚,dart告诉你该怎么用

    目录 简介 dart中的URI encode和decode 解析URI 总结 简介 如果我们要访问一个网站,需要知道这个网站的地址,网站的地址一般被称为URL,他的全称是Uniform Resourc ...

  4. 洛谷 P3643 - [APIO2016]划艇(dp)

    题面传送门 一道难度中等的 \(dp\)(虽然我没有想出来/kk). 首先一眼 \(dp_{i,j}\) 表示考虑到第 \(i\) 个学校,第 \(i\) 个学校派出了 \(j\) 个划艇的方案数,转 ...

  5. EXCEL——排序函数RANK,6种花式使用技巧

    我们在实际工作中,常常把RANK函数用于对一列数据的基本排序,即从大到小的排序方法,那你还知道它的其他什么用法吗? 今天就给大家系统的分享下RANK函数的用法,分享的内容主要为以下这6种技巧. 1.升 ...

  6. lua_newthread的真正意义

    lua_newthread 这个接口,存在误导性,很多人第一次试图用它来解决多线程问题时,都会入坑. 实际上,这个接口真正的用法,是给那些在lua更底层的某些行为(通常是递归)导致了lua的栈溢出而准 ...

  7. 容器中的容器——利用Dind实现开箱即用的K3s

    我在学习 Rancher 和 Minikube 的时候,发现它们都可以在自己的容器环境中提供一个 K3s 或 K8s 集群.尤其是 Minikube ,用户可以在它的容器环境中执行 docker ps ...

  8. acute

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

  9. 在 windows 系统上 安装与配置 PHP + Apache

    参考:http://www.cnblogs.com/pharen/archive/2012/02/06/2340628.html 在大学时候上过一门PHP课时,因为课堂需要配置过一次PHP+Mysql ...

  10. 双向循环链表模板类(C++)

    双向链表又称为双链表,使用双向链表的目的是为了解决在链表中访问直接前驱和后继的问题.其设置前驱后继指针的目的,就是为了节省其时间开销,也就是用空间换时间. 在双向链表的每个节点中应有两个链接指针作为它 ...