c++ std::enable_shared_from_this作用

news2024/12/24 9:30:09

enable_shared_from_this 是什么

std::enable_shared_from_this 是一个类模板,用来返回指向当前对象的shared_ptr智能指针。在说明它的作用前我们可以看一下如下代码:

demo.cpp

#include <memory>
#include <iostream>
     
class A
{
public:
    A() { std::cout << "A()" << std::endl; }
    ~A() { std::cout << "~A()" << std::endl; }

    std::shared_ptr<A> getSharedPtr()
    {
        std::shared_ptr<A> ptr(this);
         return ptr;
    }
};
     
int main()
{
    std::shared_ptr<A> ptr1(new A());
    std::shared_ptr<A> ptr2 = ptr1->getSharedPtr();
     
    return 0;
}

类 A 中有一个函数 getSharedPtr() 函数,用来返回指向当前对象的一个shared智能打针。其实就是用 this 构造了一个智能指针进行返回,执行结果如下:
在这里插入图片描述
看着好像没什么问题,别着急,再看下一个例子:

class B
{
public:
    B() { 
        m_age = new int(10);
        std::cout << "B()" << std::endl; 
        
    }
    ~B() { 
        std::cout << "~B()" << std::endl; 
        if (m_age){
            delete m_age;
            m_age = nullptr;
        }
    }

    std::shared_ptr<B> getSharedPtr()
    {
        std::shared_ptr<B> ptr(this);
         return ptr;
    }
private:
    int* m_age;
};

int main()
{
    std::shared_ptr<B> ptr1(new B());
    std::shared_ptr<B> ptr2 = ptr1->getSharedPtr();
     
    std::cout << ptr1.use_count() << std::endl; // 输出引用计数
    std::cout << ptr2.use_count() << std::endl; // 输出引用计数
    return 0;
}

与类A不同的是,类B有一个在堆上创建的成员,我们再来看一下运行结果:
在这里插入图片描述
可以看到程序再运行到最后时刻崩溃了,报错:free(): invalid pointer,free 了无效的指针。我们应该能看到是重复释放的问题,这里我们将裸指针赋给了智能指针,这样做潜在的危险就是对象被多次释放。

细心的小伙伴肯定看到了,智能指针ptr1 和 ptr2 的引用计数都是 1,在程序执行结束的时候都会释放一次资源,导致程序崩溃。enable_shread_from_this 的作用就是解决这个问题,示例代码如下:

class C: public std::enable_shared_from_this<C>
{
public:
    C() { 
        m_age = new int(10);
        std::cout << "C()" << std::endl; 
        
    }
    ~C() { 
        std::cout << "~C()" << std::endl; 
        if (m_age){
            delete m_age;
            m_age = nullptr;
        }
    }

    std::shared_ptr<C> getSharedPtr()
    {
        return shared_from_this();
    }
private:
    int* m_age;
};

int main()
{
    std::shared_ptr<C> ptr1(new C());
    std::shared_ptr<C> ptr2 = ptr1->getSharedPtr();
     
    std::cout << ptr1.use_count() << std::endl;
    std::cout << ptr2.use_count() << std::endl;
    return 0;
}

运行结果如下:
在这里插入图片描述

可以看到,此时两个智能指针的引用计数都为2,这两个智能指针指向了相同的资源。在 main 函数退出后,两个智能指针依次释放,引用计数依次减一,直至为0,资源成功释放。

推荐一个零声学院免费教程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/449261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

web实验(3)

应用JavaScript编写留言的功能&#xff0c;在文本中输入文字提交后&#xff0c;在下方进行显示。 提示&#xff1a;可将下方内容以列表体现&#xff0c;提交时动态创建列表的项。可使用以下两种方式之一的方法&#xff1a; 使用CreateElenment动态创建li标签及li中的文本 在列…

PADS-LOGIC项目原理图设计

最小板原理图设计 目录 1 菜单与工具使用 2 常用设置 2.1选项卡 2.2 图纸设置 2.3 颜色设置 3 设计技巧 3.1 模块化设计思路 3.2 元件放置 3.3 走线及连接符 4 原理图绘制 4.1 POWER原理图设计 4.2 MCU原理图设计 4.2.1晶振电路 4.2.2复位电路 4.2.3 BOOT电路 …

Windows 11快捷键功能大全 28个Windows 11快捷键功能介绍

Windows 11快捷键功能大全 28个Windows 11快捷键功能介绍 1. WinA 打开快速设置面板2. WinB 快速跳转系统托盘3. WinC 打开Microsoft Teams4. WinD 快速显示桌面5. WinE 打开资源管理器6. WinF 一键提交反馈7. WinG 启动Xbox Game Bar8. WinH 语音听写9. WinI 打开设置10. WinK…

如何正确高效地学习android开发?

每一个能成为行业大佬的人&#xff0c;一定有自己独特的方法… 之所以能成为大佬&#xff0c;是因为他们会有自己独特的见解&#xff0c;在一次次的尝试中不断否定&#xff0c;然后一次次的确定&#xff0c;一个程序员想要精益求精&#xff0c;必须要有高效的学习方法和良好的…

Spring Cloud Alibaba基于Sentinel实现限流降级自定义配置结果

hello&#xff0c;你好呀&#xff0c;我是灰小猿&#xff0c;一个超会写bug的程序员&#xff01; sentinel作为SpringCloudAlibaba的基本组件&#xff0c;在进行熔断、限流、降级等方面具有十分重要的作用&#xff0c;而且其基于Web界面对接口进行限流配置&#xff0c;使得实时…

环形链表II(链表篇)

给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整…

伪原创文章生成器-伪原创工具在线使用

文章伪原创工具 在如今数字时代&#xff0c;内容创作已经成为了一项必不可少的营销策略。然而&#xff0c;创作原创内容需要相当的时间和精力&#xff0c;尤其是对于需要大量输出内容的企业或个人而言。这时&#xff0c;文章伪原创工具就成为了一种快速、高效的选项。在本文中…

Doris(15):物化视图

1 概念 物化视图是将预先计算&#xff08;根据定义好的 SELECT 语句&#xff09;好的数据集&#xff0c;存储在 Doris 中的一个特殊的表。 物化视图的出现主要是为了满足用户&#xff0c;既能对原始明细数据的任意维度分析&#xff0c;也能快速的对固定维度进行分析查询。 首…

【C++】布尔类型(bool)

目录​​​​​​​ 1、缘起 2、笔记整理 4、用法 4.1、布尔变量的定义和初始化 4.2、布尔类型的运算符 4.3、布尔类型的条件语句 4.4、布尔类型的循环语句 5、总结 1、缘起 最近在 BiliBili 黑马程序员学习 C 编程语言&#xff0c;今天学习到了 布尔&#xff08;b…

算法套路十二——回溯法之排列型回溯

算法套路十二——回溯法之排列型回溯 该节是在第十节回溯法之子集型回溯的基础上进行描写&#xff0c;组合型回溯会在子集型回溯的基础上判断所选子集是否符合组合要求&#xff0c; 故请首先阅读第十节算法套路十——回溯法之子集型回溯 算法示例一&#xff1a;LeetCode46. 全…

windows环境安装tensorflow-gpu-2.10.1

Tensorflow 2.10是最后一个在本地windows上支持GPU的版本 1. 通过.whl文件方式安装2.创建anaconda虚拟环境3.安装对应的cuda与cudnn版本&#xff0c;local不必装cuda和cudnn4. 测试tensorflow gpu是否可用 1. 通过.whl文件方式安装 .whl文件的下载地址&#xff1a; tensorflow…

Linux — 线程概念和线程控制

目录 一、 线程的概念 什么是线程&#xff1f; 线程的优点 线程的缺点 线程异常 线程用途 二、线程的控制 创建线程 pthread_create函数 线程终止 pthread_exit函数 pthread_cancel函数 线程等待 pthread_join函数 分离线程 一、 线程的概念 之前的文章说过每个进程有…

IDE后端启动JetLinks 物联网基础平台(2.x)

目录 一、官网 二、文档中心 三、下载源码 四、安装依赖 五、IDE配置 六、修改配置文件&#xff1a;jetlinks-standalone/src/main/resources/application.yml 七、启动项目&#xff08;项目会自动建表&#xff09; 一、官网 JetLinkshttps://www.jetlinks.cn/#/ 二、…

率先实现One-box量产后,这家厂商重磅发布智能底盘“三步走”战略

率先实现One-box和Two-box产品量产之后&#xff0c;利氪科技向业界发布了重要的产品布局规划及进展。 在4月18日开幕的上海国际车展上&#xff0c;利氪科技重磅发布了全新的智能化线控底盘产品矩阵&#xff0c;同时发布了智能底盘“三步走”计划。据了解&#xff0c;利氪科技将…

数据结构(五)—— 栈与队列

文章目录 前言一、基础1.1 stack1.2 queue 二、题2.1 232 用栈实现队列2.2 225 用队列实现栈2.3 20 有效的括号2.4 1047 删除字符串中的所有相邻重复项 前言 灵魂四问&#xff1a; 1、C中stack&#xff0c;queue 是容器么&#xff1f; 答&#xff1a;不是&#xff0c;而是容器…

高数基础3

目录 极限的概念&#xff0c;性质以及存在准则 求极限的方法 ​编辑 常用的基本极限 1的无穷次方常用的结论 例题&#xff1a; 方法2&#xff1a;利用等价无穷小代换求极限 例题&#xff1a; 常用的等价无穷小 利用有理运算法则求极限 例题 极限的概念&#xff0c;性质以…

【C语言】函数讲解(上)

【C语言】函数讲解&#xff08;上&#xff09; 1.函数是什么2.C语言中函数的分类2.1库函数2.1.1如何学会使用库函数 2.2.自定义函数 3.函数的参数3.1实际参数&#xff08;实参&#xff09;3.2形式参数&#xff08;形参&#xff09; 4.函数调用4.1传值调用4.2传址调用4.3练习 所…

Redis分布式锁实现方案

一、什么是分布式锁&#xff0c;与本地锁有什么区别 本地锁&#xff1a; 解决同一进程内多个线程操作同一资源的问题。 分布式锁&#xff1a; 解决多个进程同时操作同一资源的问题。 二、Redis的SETNX Redis之所以能实现分布式锁&#xff0c;得益于Redis的单线程处理模式&am…

Macbook(苹果电脑) VSCode 创建简单c++程序 配置C++开发环境

1.打开 Terminal 终端&#xff08;Command空格&#xff0c;输入Terminal&#xff09;。 1.1 输入如下指令&#xff0c;查看是否显示版本信息。 clang --version 1.2 如果出现版本信息&#xff0c;则跳过&#xff0c;否则输入 xcode-select --install 2. 为 VS Code 安装插件 …

docker中的四种网络模式

docker中的四种网络模式 实现原理四类网络模式host模式container模式none模式bridge模式 实现原理 Docker使用Linux桥接&#xff0c;在宿主机虚拟一个Docker容器网桥(docker0)&#xff0c;Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址&#xff0c;称为Con…