0

0

C++智能指针shared_ptr的作用?(自动管理内存引用计数)

穿越時空

穿越時空

发布时间:2026-01-15 14:09:11

|

771人浏览过

|

来源于php中文网

原创

shared_ptr解决多对象共享堆内存时的手动管理难题,通过引用计数自动释放资源;每个实例绑定控制块记录引用数,拷贝增、析构减,归零时delete;须避免裸指针重复构造,推荐make_shared或拷贝创建。

c++智能指针shared_ptr的作用?(自动管理内存引用计数)

shared_ptr 解决什么问题

手动管理动态内存时,newdelete 容易配对失败,导致内存泄漏或重复释放。当多个对象或函数需要共享同一块堆内存(比如一个数据结构被多个模块读写),用裸指针根本无法安全判断“现在还能不能删”。shared_ptr 就是为这种场景设计的:它把“谁还在用这块内存”这个信息显式记录下来,靠引用计数自动决定何时释放。

引用计数怎么工作的

每个 shared_ptr 实例背后绑着一个控制块(control block),里面存着指向实际对象的指针和一个引用计数。每次拷贝构造、赋值或作为参数传入,计数加 1;超出作用域、重置或被赋值为另一个 shared_ptr 时,计数减 1。计数归零,控制块才调用 delete 销毁对象。

注意:两个指向同一地址的 shared_ptr 必须由同一个原始 shared_ptr 派生,否则控制块不共享,会 double-delete:

int* raw = new int(42);
std::shared_ptr a(raw);  // ❌ 危险!a 独占控制块
std::shared_ptr b(raw);  // ❌ b 另建控制块 → 后续析构两次 delete raw

正确做法是始终用 std::make_shared 构造,或通过拷贝已有 shared_ptr

立即学习C++免费学习笔记(深入)”;

AOXO_CMS建站系统企业通用版1.0
AOXO_CMS建站系统企业通用版1.0

一个功能强大、性能卓越的企业建站系统。使用静态网页技术大大减轻了服务器负担、加快网页的显示速度、提高搜索引擎推广效果。本系统的特点自定义模块多样化、速度快、占用服务器资源小、扩展性强,能方便快捷地建立您的企业展示平台。简便高效的管理操作从用户使用的角度考虑,对功能的操作方便性进行了设计改造。使用户管理的工作量减小。网站互动数据可导出Word文档,邮件同步发送功能可将互动信息推送到指定邮箱,加快企业

下载
auto a = std::make_shared(42);  // ✅ 推荐
auto b = a;                            // ✅ 共享同一控制块

和 unique_ptr、weak_ptr 的关键区别

unique_ptr 是独占语义:不可拷贝,只能移动,适合“我管到底”的场景;shared_ptr 是共享语义:可拷贝,但有运行时开销(控制块内存 + 原子计数);weak_ptr 不增加引用计数,只用于打破循环引用 —— 比如父子节点互相持有 shared_ptr,就会导致计数永远不归零。

  • 性能敏感且所有权明确?优先选 unique_ptr
  • 需要多处共享且生命周期不确定?用 shared_ptr
  • 共享中还要观察对象是否还活着(比如缓存、监听器列表)?配合 weak_ptr::lock() 使用

容易踩的坑

常见错误不是语法问题,而是语义误用:

  • 把裸指针传给多个 shared_ptr 构造函数 → double-delete
  • 在类成员里用 shared_ptr 持有 this(比如异步回调里保存 shared_from_this()),但忘了该类必须继承自 std::enable_shared_from_this
  • 在循环引用场景下没引入 weak_ptr,导致内存永远不释放
  • 误以为 shared_ptr 能管理对象或全局对象 —— 它只应配合堆分配(newmake_shared

引用计数本身是线程安全的(增减原子),但所指对象的访问仍需额外同步 —— 这点常被忽略。

相关专题

更多
c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

98

2025.10.23

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

534

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

14

2026.01.06

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

389

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

571

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

389

2023.07.18

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号