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. 洛谷 P5044 - [IOI2018] meetings 会议(笛卡尔树+DP+线段树)

    洛谷题面传送门 一道笛卡尔树的 hot tea. 首先我们考虑一个非常 naive 的区间 DP:\(dp_{l,r}\) 表示区间 \([l,r]\) 的答案,那么我们考虑求出 \([l,r]\) ...

  2. mount 挂载详解

    挂接命令(mount) 首先,介绍一下挂接(mount)命令的使用方法,mount命令参数非常多,这里主要讲一下今天我们要用到的. 命令格式:mount [-t vfstype] [-o option ...

  3. Demo04分解质因数

    package 习题集1;import java.util.Scanner;//将一个正整数分解质因数.例如输入90,打印出90=2*3*3*5public class Demo04 { public ...

  4. MySQL全面瓦解29:使用Partition功能实现水平分区

    1 回顾 上一节我们详细讲解了如何对数据库进行分区操作,包括了 垂直拆分(Scale Up 纵向扩展)和 水平拆分(Scale Out 横向扩展) ,同时简要整理了水平分区的几种策略,现在来回顾一下. ...

  5. mysql数据查询语言DQL

    DB(database)数据库:存储数据的'仓库',保存了一系列有组织的数据 DBMS(Database Management System)数据库管理系统:用于创建或管理DB SQL(Structu ...

  6. 使用Redis实现令牌桶算法

    在限流算法中有一种令牌桶算法,该算法可以应对短暂的突发流量,这对于现实环境中流量不怎么均匀的情况特别有用,不会频繁的触发限流,对调用方比较友好. 例如,当前限制10qps,大多数情况下不会超过此数量, ...

  7. A Child's History of England.19

    The King was at first as blind and stubborn as kings usually have been whensoever [每当] they have bee ...

  8. 基于MQTT协议实现远程控制的"智能"车

    智能,但不完全智能 虽然我不觉得这玩意儿有啥智能的,但都这么叫就跟着叫喽. 时隔好几天才写的 其实在写这篇博文的时候我已经在做升级了,并且已经到了中后期阶段了. 主要是业余时间做着玩,看时间了. 规格 ...

  9. Java偏向锁浅析

    偏向锁的定义 顾名思义,偏向锁会偏向第一个访问锁的线程. 如果在接下来的运行过程中,该锁没有被其他线程访问,这持有偏向锁的线程将永远不需要同步 如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线 ...

  10. 数仓day02

    1. 什么是ETL,ETL都是怎么实现的? ETL中文全称为:抽取.转换.加载  extract   transform  load ETL是传数仓开发中的一个重要环节.它指的是,ETL负责将分布的. ...