make_shared、shared_ptr、enable_shared_from_this

【C++11】shared_ptr智能指针使用详解 shared_ptr智能指针使用详解 阅读详情

它们的区别

     在于 make_shared 只有一次内存申请操作,而 shared_ptr 构造函数会有两次。

shared_ptr 对象会管理两部分内容,

  • 控制块,比如引用计数、deleter 等等
  • 要被管理的对象

当调用 make_shared 的时候,会申请一份足够大的内存同时给控制块和对象使用。而 shared_ptr 构造函数会分别为控制块和对象调用内存申请,详情可以参考 cpprefrence – implementation notes。当然 make_shared 这样的做法也是有弊端的。当 shared_ptr 都离开了各自的作用域,被管理的对象也无法被析构。只有所有的 weak_ptr 也都离开了各自的作用域,这时候,一次申请的内存才会被释放掉。

std::enable_shared_from_this

定义于头文件 <memory>

template< class T > class enable_shared_from_this;

(C++11 起)

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 的所有权。


注意

enable_shared_from_this 的常见实现为:其内部保存着一个对 this 的弱引用(例如 std::weak_ptr )。 std::shared_ptr 的构造函数检测无歧义且可访问的 (C++17 起) enable_shared_from_this 基类,并且若内部存储的弱引用未为生存的 std::shared_ptr 占有,则 (C++17 起)赋值新建的 std::shared_ptr 为内部存储的弱引用。为已为另一 std::shared_ptr 所管理的对象构造一个 std::shared_ptr ,将不会考虑内部存储的弱引用,从而将导致未定义行为。

只允许在先前已被std::shared_ptr 管理的对象上调用 shared_from_this 。否则调用行为未定义 (C++17 前)抛出 std::bad_weak_ptr 异常(通过 shared_ptr 从默认构造的 weak_this 的构造函数) (C++17 起)。

enable_shared_from_this 提供安全的替用方案,以替代 std::shared_ptr<T>(this) 这样的表达式(这种不安全的表达式可能会导致 this 被多个互不知晓的所有者析构,见下方示例)。

示例

#include <memory>
#include <iostream>
 
struct Good: std::enable_shared_from_this<Good> // 注意:继承
{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};
 
struct Bad
{
    // 错误写法:用不安全的表达式试图获得 this 的 shared_ptr 对象
    std::shared_ptr<Bad> getptr() {
        return std::shared_ptr<Bad>(this);
    }
    ~Bad() { std::cout << "Bad::~Bad() called\n"; }
};
 
int main()
{
    // 正确的示例:两个 shared_ptr 对象将会共享同一对象
    std::shared_ptr<Good> gp1 = std::make_shared<Good>();
    std::shared_ptr<Good> gp2 = gp1->getptr();
    std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';
 
    // 错误的使用示例:调用 shared_from_this 但其没有被 std::shared_ptr 占有
    try {
        Good not_so_good;
        std::shared_ptr<Good> gp1 = not_so_good.getptr();
    } catch(std::bad_weak_ptr& e) {
        // C++17 前为未定义行为; C++17 起抛出 std::bad_weak_ptr 异常
        std::cout << e.what() << '\n';    
    }
 
    // 错误的示例,每个 shared_ptr 都认为自己是对象仅有的所有者
    std::shared_ptr<Bad> bp1 = std::make_shared<Bad>();
    std::shared_ptr<Bad> bp2 = bp1->getptr();
    std::cout << "bp2.use_count() = " << bp2.use_count() << '\n';
} // UB : Bad 对象将会被删除两次

可能的输出:

gp2.use_count() = 2
bad_weak_ptr
bp2.use_count() = 1
Bad::~Bad() called
Bad::~Bad() called
*** glibc detected *** ./test: double free or corruption

记一次使用make_shared遇到的坑!

        

遇到问题及解决方案
  • 问题:m_httpClient = std::make_shared(std::bind(&LogReporter::isExit, this)); weekref是大于1的时候会卡死【关于C++11中的make_shared_c++ make_shared_桃溪小小生的博客-优快云博客】
    • 原因:make_shared跟week_ptr一起用需要注意,control block和R被合并为了一块内存空间,对象释放需要等待弱引用离开,否则会一直等
  • 问题:shared_from_this返回空
    • 原因:构造时没有用共享指针接管
    • 解决:单例新增共享接管
【C++11】unique_ptr智能指针使用详解 C++11 unique_ptr智能指针使用详解 阅读详情

相关推荐

C++智能指针实战指南:从shared_ptr到weak_ptr的多线程安全应用

本文深入探讨了C++智能指针在多线程环境下的安全应用,重点解析了shared_ptr、unique_ptr和weak_ptr的使用场景与最佳实践。通过实际代码示例,展示了如何利用智能指针解决内存管理、循环引用和线程安全等核心问题,帮助开发者编写更健壮、高效的C++代码。

weixin_29021291的博客 248

c++ 之 make_shared

c++ 之 make_shared

xiaozhi 1318

C++特性之智能指针shared_ptr

C++特性之智能指针shared_ptr

yohnyang的博客 1227

C++ make_shared使用

C++内存分四大块 全局 主函数运行前使用,初始化 静态 变量第一次使用前,初始化 以上两块内存都会在程序结束后自动释放 堆区 由程序员管理,C++管理方法有new delete等关键字 栈区 由编译器管理,存放程序的局部变量和参数 因此我们需要关注堆区的内存管理。内存管理经常会碰到忘记释放造成的内存泄露。 在C++中引入了智能指针,有shared_ptr,unique_ptr和weak_ptr。 shared_ptr 工作中shared_ptr用得比较多,今天做个总结 使用智能指针,需

duringsummer的博客 3万+

放弃FFT全频计算!在STM32F407上用DFT单点计算提速50%的优化技巧

本文详细介绍了在STM32F407上通过DFT单点计算实现比FFT快50%的优化技巧,特别适用于生物阻抗分析、振动监测等只需关注单一频点的嵌入式场景。通过预计算相位角、查表法和混合精度计算等策略,显著提升计算效率和内存利用率,同时保持高精度。

weixin_28738397的博客 191

ROS智能车定位导航仿真+功能包自带的地图实现+自己建立的地图实现

ROS智能车定位导航仿真一、前言二、效果图三、准备工作[1.在Ubuntu上安装ROS Kinetic](https://blog.youkuaiyun.com/qq_42585108/article/details/104327661)2.创建ROS工作区间①1创建racecar_ws和src文件夹②初始化工作空间③下载racecar源代码包,并编译工程四、启动仿真1.设置环境变量2.启动地图五、建图1.启动slam和rviz2 控制车辆(左侧有个控制窗口),WASD控制前左后右的运动就可以建图了:3.新建终端保存地

qq_42585108的博客 1万+

细讲C++【6】:C++智能指针进阶详解|enable_shared_from_this、weak_ptr、循环引用、容器存储、make_shared/make_unique底层

C++智能指针进阶详解|enable_shared_from_this、weak_ptr、循环引用、容器存储、make_shared/make_unique底层

2501_90355051的博客 536

终端以太网接入Internet实验

实验过程: 1.布局 2.连接 3.配置Route0和Route1 4.配置RIP 5.static: 6.查看Route0,Route1的路由表: 7.完成PC2和server0 IP地址,子网掩码和默认网关地址的配置: 8.命令行: 9.启动PC0桌面下的PPPoe宽带连接程序: 10.启动PC1桌面下的PPPoe宽带连接程序: 11.验证PC0和PC2的ICMP报文传输过程 12.验证PC1和server0的ICMP报文传输过程 关键命令说明

chaojidagouzi的博客 4081

C++ 中 shared_ptr 的创建:构造函数 vs make_shared 深度解析 + enable_shared_from_this 安全用法

s​​​​​​​是C++ 标准库为优化shared_ptr创建而设计的工具,凭借一次内存分配、高异常安全性、简洁语法成为常规场景下的首选;而直接使用构造函数创建shared_ptr则以灵活性取胜,能处理自定义删除器、私有构造、数组管理等无法覆盖的特殊场景。在实际开发中,应遵循优先使用 make_shared,特殊场景用构造函数的原则,同时注意的内存释放滞后性问题,避免因悬空的weak_ptr造成不必要的内存浪费。理解两种创建方式的底层内存实现,才能根据业务场景做出最优选择,让shared_ptr。

W2303576573的博客 647

算法竞赛入门到进阶 --- 完整学习路线(含知识点讲解)

前言: 咳咳,接触算法竞赛也有一年了,却从来都没有进行过一次系统的学习,稀里糊涂的就这么搞了半年,如今,我决定认认真真的进行一次系统的复盘。嗯嗯,先把大体路线列出来,然后往后每天搞几篇,可能大三能完成,可能永远也不能写完这些,我只能慢慢来,一起共勉吧。冲了!(主要是太菜了,不系统学习下,怕是铜牌都拿不到呀!) 算法竞赛入门到进阶一、sort函数自定义排序二、c++容器的使用1.vector动态数组2.stack栈3.queue队列4.list链表5.set集合6.map映射三、二进制子集生成四、bfs.

qq_43514659的博客 2万+

从零构建AI辅助逆向分析环境:JADX-MCP与LLM的实战集成指南

本文详细介绍了如何从零构建AI辅助逆向分析环境,通过集成JADX-MCP与LLM技术,提升Android应用逆向工程效率。文章涵盖环境搭建、插件安装、MCP服务器配置及实战案例分析,帮助开发者快速掌握AI在代码理解、漏洞挖掘和自动化文档生成中的应用。

weixin_27875131的博客 836

shared_ptr和weak_ptr

程序中需要管理各种各样的资源,为了避免内存泄露,必须确保在资源再也不需要时释放资源,智能指针提供了这一功能。C++标准提供了两大类智能指针,这里主要介绍shared_ptr。多个shared_ptr可以共享同一个资源,并在最后一个拥有资源的shared_ptr被销毁时释放资源。 1、deleter 2、weak_ptr ...

csdn_cjc的博客 2701

理想L9高通QAM8797座舱域控制器全拆解|全网独家复现 硬件架构升级、电源散热优化、多屏低延迟交互、车机系统赋能高端智能座舱落地

随着智能汽车向舱驾一体、全域智能化、多模交互方向迭代,传统单一功能座舱芯片已无法满足多屏高刷渲染、全车AI语音、车内视觉感知、高速车载通信的叠加算力需求。2026款全新理想L9作为旗舰级智能SUV,全面搭载高通新一代旗舰座舱域控制器QAM8797,搭配自研马赫M100 AI芯片、国产车规主控芯片,构建起高性能、高可靠、低延迟的车载中央计算平台。

getusushu的博客 376

unique_ptr、shared_ptr、weak_ptr的区别与联系

​ 因为在异步调用中,存在一个保活机制,异步函数执行的时间点我们是无法确定的,然而异步函数可能会使用到异步调用之前就存在的变量。为了保证该变量在异步函数执期间一直有效,我们可以传递一个指向自身的share_ptr给异步函数,这样在异步函数执行期间share_ptr所管理的对象就不会析构,所使用的变量也会一直有效了(保活)。​ 坏处是,只有当强引用计数和弱引用计数都为0时,才会释放,意外的延迟了内存释放的时间。​ 所有的共享指针会占用一个弱引用计数,其余情况不操作弱引用计数,只操作强引用计数。

bhybhy123456的博客 852

AI翻译工具自动翻译日语视频生成srt中文字幕,支持离线轻松生成任意日语视频字幕!可选择支持显卡模式和cpu模式低显存也能用

【AI离线字幕神器:日语视频一键转中文字幕】推荐一款基于Faster-Whisper的本地化字幕工具,可离线生成日语视频的中文字幕(.srt格式),支持CPU/GPU加速处理。实测1小时视频最快4-5分钟完成翻译,无需联网保护隐私。操作简单只需拖拽文件,支持批量处理音频(mp3/wav)和视频(mp4/mkv)文件,还能自定义输出格式和参数调整。特别适合需要观看无字幕日语资料的用户,堪称技术宅必备神器。下载地址附后,包含详细使用教程和参数配置说明。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1万+

基于NARX和NARX-LSTM的模型辨识与MPC控制系统调试与优化

本文针对两输入单输出非线性系统,提出基于NARX和NARX-LSTM的模型辨识与MPC控制优化方案。系统输入为固定量u1和可调量u2(8.5-140),输出目标为-0.58。现有模型存在辨识精度不足、历史输出依赖过重、预测偏差等问题。解决方案包括:数据差分处理改善非平稳性、调整延迟阶数优化模型结构、引入注意力机制替代手动加权、改进损失函数消除预测偏差。MPC控制器将结合优化模型,考虑控制变量步长约束(≥2),实现输出稳定控制。通过系统性的模型调试与控制算法优化,最终形成完整的非线性系统辨识与控制框架。

huanghm88的专栏 127

C++ enable_shared_from_this:安全获取自身shared_ptr的原理与实践

在C++智能指针体系中,std::shared_ptr通过引用计数机制实现对象的自动生命周期管理,有效防止内存泄漏。其核心原理是通过控制块记录引用计数,当多个智能指针共享同一对象时,它们共享同一个控制块。这一机制在面向对象编程中尤为重要,特别是在涉及回调、异步操作和事件处理时,需要对象方法内部安全地获取指向自身的智能指针。然而,直接使用原始指针this创建新的shared_ptr会导致双重控制块问题,引发未定义行为。std::enable_shared_from_this模板类正是为解决这一困境而设计,它允

weixin_33290540的博客 305

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

C++中的智能指针std::shared_ptr是线程安全的吗?以及它的详细实现原理

C++智能指针使用指南 本文重点介绍了C++中std::shared_ptr和std::weak_ptr的使用方法及实现原理。主要内容包括: shared_ptr核心用法 推荐使用std::make_shared创建,避免单独new导致的两次内存分配 支持共享所有权,通过引用计数自动管理资源 可通过reset()释放资源或变更所有权 提供自定义删除器功能,支持非内存资源管理 C++17起原生支持动态数组 weak_ptr核心特性 作为"弱引用"不增加引用计数,解决循环引用问题 必须通过l

红军不怕远征难,万水千山只等闲 1302

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C++ 中 shared ptr 详解:原理与线程安全性分析

操作 | 线程安全性 | 说明 || 拷贝 shared_ptr | 安全 | 引用计数原子递增 || 析构 shared_ptr | 安全 | 引用计数原子递减 || 移动 shared_ptr | 安全 | 不涉及引用计数修改 || 修改被管理对象 |不安全| 需要额外的同步机制 || use_count() | 安全(但值可能过期) | 返回值是近似值 || reset() | 安全 | 原子地替换管理的对象 |内部结构shared_ptr包含对象指针和控制块指针。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 674

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

深入解析C++智能指针:enable_shared_from_this的正确使用场景与实践

本文深入解析了C++智能指针中enable_shared_from_this的正确使用场景与实践。针对多个shared_ptr管理同一对象导致双重释放的经典陷阱,文章阐述了enable_shared_from_this如何通过内部弱指针机制,安全地从类成员函数内部返回指向自身的shared_ptr,并重点探讨了其在多线程环境下保障对象生命周期安全的关键作用与最佳实践。

weixin_30300225的博客 419

C++内存管理:shared_ptr/weak_ptr源码(长文预警)

本文主要讲述c++提供的shared_ptrweak_ptr和,以及详解MSVC中STL提供的智能指针源码。

木牛的博客 407

C++ unique_ptr、shared_ptr、weak_ptr全面解析

对make出来的智能指针和new出来的智能指针的区别做了详细介绍,同时对shared_ptr和weak_ptr之间的关系做了全面剖析

2401_86112944的博客 1335

指针嵌套指针 拷贝_C++智能指针小结

C++中的智能指针包括auto_ptr, unique_ptr, shared_ptr, weak_ptr. 其中 auto_ptr已被弃用.unique_ptrunique_ptr是大部分情况下的首选, 体现独占的语义. 当unique_ptr被销毁时, 其指向的原始指针也自动被销毁. unique_ptr体现资源的独占, 因此无法被拷贝, 没有拷贝构造和拷贝赋值函数. 但是unique_ptr...

weixin_39688170的博客 586

C++ shared_ptr 智能指针:引用计数、循环引用与实战避坑

在 C++ 资源管理中,裸指针容易引发内存泄漏、悬空指针与重复释放,而 RAII 与智能指针将所有权语义写入类型系统。shared_ptr 通过控制块与引用计数记录共享拥有者,最后一个强引用离开时自动回收资源,weak_ptr 则用于观测与打破循环引用。这种机制在异步任务、缓存、观察者模式等场景中价值显著,能大幅降低手动 delete 的心智负担。理解 make_shared 的内存布局、强/弱引用分工以及线程安全边界,是避免循环引用、double free 与性能退化的关键。从裸指针到 shared_pt

weixin_34265814的博客 169

XiyouLinux Group知识分享——告别手动delete:C++智能指针实战与底层探析

文章代码实例(私家车/公交车)来自https://github.com/AnnFengDeYe/OJ-Summary

hgc_qwe的博客 378
上一篇: 以vector的遍历形式遍历map操作数据误区&&map中的[]运算符原理!
下一篇: 当单例类需要支持共享时遇到的问题以及解决方案
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ปรัชญา แค้วคำมูล

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值