全面理解-c++11中的智能指针
在 C++ 中,智能指针(Smart Pointers) 是用于自动管理动态分配内存的类模板,遵循 RAII(Resource Acquisition Is Initialization) 原则,确保资源在生命周期结束时被正确释放,避免内存泄漏。C++11 引入了三种主要的智能指针:std::unique_ptr、std::shared_ptr 和 std::weak_ptr,取代了 C++98 中不安全的 std::auto_ptr。
1. 为什么需要智能指针?
-
手动管理内存的痛点:
-
忘记
delete导致内存泄漏。 -
重复
delete导致未定义行为。 -
异常安全问题(未捕获异常时资源无法释放)。
-
-
智能指针的核心作用:
-
自动释放内存:对象生命周期结束时自动调用
delete。 -
明确所有权语义:通过所有权模型管理资源。
-
2. 主要智能指针类型
(1) std::unique_ptr(独占所有权)
-
所有权模型:唯一拥有资源,不可复制,但可通过
std::move转移所有权。 -
适用场景:
-
资源有唯一拥有者。
-
需要轻量级、零开销的内存管理。
-
-
基本用法:
#include <memory>// 创建 unique_ptr std::unique_ptr<int> ptr1 = std::make_unique<int>(10); // C++14 起推荐 std::unique_ptr<int> ptr2(new int(20)); // 直接构造// 转移所有权 std::unique_ptr<int> ptr3 = std::move(ptr1); // ptr1 变为 nullptr// 自定义删除器(可选) auto deleter = [](int* p) { delete p; }; std::unique_ptr<int, decltype(deleter)> ptr4(new int(30), deleter);
(2) std::shared_ptr(共享所有权)
-
所有权模型:通过引用计数(
use_count())管理资源,多个指针共享所有权。 -
适用场景:
-
多个对象需要共享同一资源。
-
资源生命周期不确定,需自动管理。
-
-
基本用法:
// 创建 shared_ptr std::shared_ptr<int> ptr1 = std::make_shared<int>(10); // 推荐(高效) std::shared_ptr<int> ptr2(new int(20)); // 直接构造// 共享所有权 std::shared_ptr<int> ptr3 = ptr1; // 引用计数 +1(ptr1.use_count() == 2)// 自定义删除器(可选) std::shared_ptr<int> ptr4(new int(30), [](int* p) { delete p; });
(3) std::weak_ptr(弱引用)
-
所有权模型:不增加引用计数,用于解决
shared_ptr的循环引用问题。 -
适用场景:
-
观察
shared_ptr管理的资源,不参与所有权管理。 -
打破
shared_ptr的循环引用(如双向链表、观察者模式)。
-
-
基本用法:
std::shared_ptr<int> sharedPtr = std::make_shared<int>(42); std::weak_ptr<int> weakPtr = sharedPtr;// 使用时提升为 shared_ptr if (auto tempPtr = weakPtr.lock()) { // 检查资源是否有效std::cout << *tempPtr << std::endl; // 输出 42 }
(4) std::auto_ptr(已弃用)
-
问题:所有权转移语义不明确(通过拷贝构造函数转移所有权),易导致悬空指针。
-
替代方案:使用
std::unique_ptr。
3. 智能指针的核心对比
| 特性 | std::unique_ptr | std::shared_ptr | std::weak_ptr |
|---|---|---|---|
| 所有权 | 独占 | 共享 | 无(弱引用) |
| 拷贝语义 | 禁止(只能移动) | 允许(引用计数增加) | 允许(不增加引用计数) |
| 性能开销 | 无 | 引用计数操作(原子操作) | 无 |
| 循环引用处理 | 不适用 | 无法解决 | 可解决 |
| 自定义删除器 | 支持(模板参数) | 支持(构造函数参数) | 不适用 |
4. 使用建议
-
优先使用
std::make_unique和std::make_shared:-
更高效(减少内存分配次数)。
-
异常安全。
auto ptr = std::make_shared<int>(42); // 替代 new -
-
避免裸指针与智能指针混用:
int* rawPtr = new int(10); std::shared_ptr<int> ptr(rawPtr); // ❌ 危险:多个 shared_ptr 可能管理同一裸指针 -
解决循环引用:
-
使用
std::weak_ptr断开shared_ptr的循环依赖。
class B; // 前向声明class A { public:std::shared_ptr<B> bPtr; };class B { public:std::weak_ptr<A> aPtr; // 使用 weak_ptr 代替 shared_ptr }; -
-
传递智能指针的规则:
-
函数参数:
-
如果函数需要接管所有权 → 按值传递
std::unique_ptr。 -
如果函数只是使用资源 → 传递裸指针或引用。
void takeOwnership(std::unique_ptr<int> ptr); // 接管所有权 void useResource(const int* ptr); // 仅使用资源 -
-
5. 智能指针的底层原理
-
std::unique_ptr:-
内部封装一个裸指针,删除时调用
delete或自定义删除器。 -
禁止拷贝构造函数和拷贝赋值运算符。
-
-
std::shared_ptr:-
包含两个指针:一个指向对象,一个指向控制块(含引用计数和删除器)。
-
引用计数为 0 时释放资源。
-
-
std::weak_ptr:-
不增加引用计数,但能检测资源是否有效。
-
6. 示例代码
(1) unique_ptr 管理动态数组
// 管理动态数组(C++11 需要指定删除器,C++14 起可直接用 unique_ptr<T[]>)
std::unique_ptr<int[]> arr(new int[5]{1, 2, 3, 4, 5});
arr[0] = 10;
(2) shared_ptr 的循环引用问题
#include <memory>class Node {
public:std::shared_ptr<Node> next;
};int main() {auto node1 = std::make_shared<Node>();auto node2 = std::make_shared<Node>();node1->next = node2; // node1 引用 node2node2->next = node1; // node2 引用 node1 → 循环引用,内存泄漏!return 0;
}
解决方案:将其中一个 shared_ptr 替换为 weak_ptr。
总结
智能指针是现代 C++ 内存管理的核心工具,通过明确所有权和自动资源释放,显著提升代码安全性和可维护性。根据场景选择:
-
唯一所有权 →
std::unique_ptr -
共享所有权 →
std::shared_ptr -
弱引用观察 →
std::weak_ptr
遵循 RAII 原则,避免手动 new/delete,是编写高质量 C++ 代码的关键。
相关文章:
全面理解-c++11中的智能指针
在 C 中,智能指针(Smart Pointers) 是用于自动管理动态分配内存的类模板,遵循 RAII(Resource Acquisition Is Initialization) 原则,确保资源在生命周期结束时被正确释放,避免内存泄…...
【jmeter】在windows中,创建的变量,在jmeter中,读取变量失败的问题,路径问题
1.0 在windows中,jmeter读取变量失败 在路径配置的时候,配置按照D:\FtpDownload\${file_name}运行之后,下载的文件,文件名出现问题 \取消了$符号的意义,所以需要更改路径 D:\\FtpDownload\\${file_name}...
【CubeMX-HAL库】STM32F407—无刷电机学习笔记
目录 简介: 学习资料: 跳转目录: 一、工程创建 二、板载LED 三、用户按键 四、蜂鸣器 1.完整IO控制代码 五、TFT彩屏驱动 六、ADC多通道 1.通道确认 2.CubeMX配置 ①开启对应的ADC通道 ②选择规则组通道 ③开启DMA ④开启ADC…...
使用 POI-TL 和 JFreeChart 动态生成 Word 报告
文章目录 前言一、需求背景二、方案分析三、 POI-TL JFreeChart 实现3.1 Maven 依赖3.3 word模板设置3.2 实现代码 踩坑 前言 在开发过程中,我们经常需要生成包含动态数据和图表的 Word 报告。本文将介绍如何结合 POI-TL 和 JFreeChart,实现动态生成 W…...
xxl-job的分片广播
目录 xxl-job的分片广播 场景引入 xxl-job简介 xxl-job的部署安装 代码编写 1.导入依赖 2.yml文件编写 3.编写xxl-job执行器配置类,维护一个xxl-job执行器的bean 4.编写第一个任务,任务名字叫firstJob 5.进入服务端,增加执行器和任务…...
MobaXterm破解会话上限限制
1. 下载安装包MobaXterm-Keygen 下载路径: https://gitcode.com/gh_mirrors/mob/MobaXterm-Keygen 2. 搭建python3环境 window下python3环境搭建可参考网站: https://blog.csdn.net/enteracity/article/details/135479689 3. 生成文件Custom.mxtpro…...
vscode设置保存时自动缩进和格式化
参考博客 如何在 VSCode 中自动缩进你的代码 | Linux 中国 省流 使用 Ctrl Shift P 来打开命令模式,搜索 Open User Settings 并按下回车你需要搜索 Auto Indent,并在 “编辑器:自动缩进(Editor: Auto Indent)” 中选择 “全部(Full)”P…...
一键查看电脑各硬件详细信息 轻松查看电脑硬件参数
今天为大家推荐两款非常实用的电脑硬件查看软件,它们能够一键快速查看电脑的各种配置信息,使用起来非常方便。 一键查看电脑各硬件详细信息 这款软件是绿色版的,无需安装,打开即可使用,文件大小仅为900多KB࿰…...
【C++11】lambda和包装器
1.新的类功能 1.1默认的移动构造和移动赋值 原来C类中,有6个默认成员函数:构造函数/析构函数/拷⻉构造函数/拷⻉赋值重载/取地址重 载/const 取地址重载,最后重要的是前4个,后两个⽤处不⼤,默认成员函数就是我们不写…...
react redux用法学习
参考资料: https://www.bilibili.com/video/BV1ZB4y1Z7o8 https://cn.redux.js.org/tutorials/essentials/part-5-async-logic AI工具:deepseek,通义灵码 安装相关依赖: 使用redux的中间件: npm i react-reduxreact-…...
前端HTML标签 meta中常见的一些属性
meta中常见的一些属性 <meta/> 标签的属性 <meta/> 是什么? <meta/> 标签主要用于表示和当前文档相关的 元数据 信息。 而 元数据(metadata),简单的来说就是描述数据的数据。例如,一个 HTML 文件是一…...
127,【3】 buuctf [NPUCTF2020]ReadlezPHP
进入靶场 吓我一跳 查看源码 点击 审计 <?php// 定义一个名为 HelloPhp 的类,该类可能用于执行与日期格式化相关的操作 class HelloPhp {// 定义一个公共属性 $a,用于存储日期格式化的模板public $a;// 定义一个公共属性 $b,用于存储…...
继承(python)
一、基础知识 (一)定义:子类能继承父类所有的公有属性和公有方法(先使用子类的方法、属性) (二)格式: class 子类名(父类名): #父类 class Ph…...
驱动开发系列36 - Linux Graphics 2D 绘制流程
一: 概述 在Linux中,2D绘制流程是操作系统、图形库、显示协议、驱动程序等多个组件协调工作的结果。整体流程如下步骤所示: 1. 客户端请求:客户端程序(如GTK、Qt应用程序)通过X11协议与Xorg-Server通信(或通过Wayland协议与Wayland合成器通信)、请求绘制2D图形,比如绘制…...
STL函数算法笔记
STL函数算法笔记 今天我们来学习的是STL库中的一些函数。首先,STL这个东西大家一定非常熟悉,里面很多的数据结构都帮了大家不少忙,那么今天我们就来说几个重要的数据结构。 向量 向量,也就是数据结构vector,你也可以称之为动态数组,本质跟数组差不多,只不过有一些好处…...
【Vue】在Vue3中使用Echarts的示例 两种方法
文章目录 方法一template渲染部分js部分方法一实现效果 方法二template部分js or ts部分方法二实现效果 贴个地址~ Apache ECharts官网地址 Apache ECharts示例地址 官网有的时候示例显示不出来,属于正常现象,多进几次就行 开始使用前,记得先…...
小红书自动化:如何利用Make批量生成爆款笔记
小红书自动化:如何利用Make制作个人自媒体中心,批量生成爆款笔记 引言 在如今信息爆炸的时代,如何高效地获取和分享优质内容,成为了每位自媒体工作者必须面对的挑战。你是否想过,如果能够将这项繁复的工作实现自动化…...
学习率调整策略 | PyTorch 深度学习实战
前一篇文章,深度学习里面的而优化函数 Adam,SGD,动量法,AdaGrad 等 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started 本篇文章内容来自于 强化学习必修课:引…...
DeepSeekMoE 论文解读:混合专家架构的效能革新者
论文链接:DeepSeekMoE: Towards Ultimate Expert Specialization in Mixture-of-Experts Language Models 目录 一、引言二、背景知识(一)MoE架构概述(二)现有MoE架构的问题 三、DeepSeekMoE架构详解(一&a…...
以下是基于巨控GRM241Q-4I4D4QHE模块的液位远程控制系统技术方案:
以下是基于巨控GRM241Q-4I4D4QHE模块的液位远程控制系统技术方案: 一、系统概述 本系统采用双巨控GRM241Q模块构建4G无线物联网络,实现山上液位数据实时传输至山下水泵站,通过预设逻辑自动控制水泵启停,同时支持APP远程监控及人工…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...
RushDB开源程序 是现代应用程序和 AI 的即时数据库。建立在 Neo4j 之上
一、软件介绍 文末提供程序和源码下载 RushDB 改变了您处理图形数据的方式 — 不需要 Schema,不需要复杂的查询,只需推送数据即可。 二、Key Features ✨ 主要特点 Instant Setup: Be productive in seconds, not days 即时设置 :在几秒钟…...
