C++ 智能指针

什么是智能指针

智能指针是自动帮你管理内存、防止内存泄漏的包装类,是现代 C++ 用来代替裸指针的工具,解决了裸指针在某些地方的痛点。比如:

1.忘记 delete ,导致内存泄漏。

2.提前 delete ,后面还要继续用,导致悬空指针,野指针。

3.异常抛出时,函数提前退出,delete 永远执行不到。

RAII

要了解智能指针,我们先从它的设计思路开始。智能指针的设计思路是 RAII (Resource Acquisition Is Initialization),这是一种 "资源获取即初始化" 的编程思想,是所有智能指针的底层原理,也是现代 C++ 管理资源的核心范式。

RAII 的核心逻辑是:把资源的生命周期,和一个栈对象的生命周期绑定在一起 。RAII 在获取资源时把资源委托给一个对象,接着控制对资源的访问,资源在对象生命周期内始终保持有效,最后在对象析构的时候释放资源,这样保障了资源的正常释放,避免资源泄漏问题

C++标准库智能指针的使用

使用智能指针需要包含头文件 <memory>

C++98:

智能指针在 C++98 就已经出现,但效果不尽人意。

auto_ptr:auto_ptr是 C++98 就出现的智能指针,但它的设计十分糟糕,属于 C++ 的一次失败的尝试。它的逻辑是:拷贝时,把拷贝对象的资源的管理权转移给拷贝对象,旧的对象会被置空。但这种置空是不会显示表现出来的,让人以为旧指针能用,如果此时访问就会报错。

C++11:

之前 C++98 搞出来的智能指针太糟糕,很多公司明令禁止使用。C++ 委员会也知道只是一个非常差劲的设计,于是在 C++11 移动语义出现后,迅速抛弃了 auto_ptr,搞出了几个新的智能指针。

unique_ptr: unique_ptr 不支持拷贝,只支持移动。unique_ptr 也会把旧的指针置空,但它的移动是显示的,也就是说你在使用它时你应该自己清楚旧指针会被置空,如果你还去访问旧指针就是你自己的问题了。在不需要拷贝的场景建议使用它。

shared_ptr :shared_ptr 支持拷贝,也支持移动。它的底层是使用引用计数的方式实现的。shared_ptr 除了支持用指向资源的指针进行构造,还支持用 make_shared 用初始化资源对象的值直接构造。

weak_ptr: weak_ptr 完全不同于以上指针,它不支持 RAII ,这也意味着不能用它直接管理资源。weak_ptr 的产生是为了解决循环引用的问题,这个后面细讲。

智能指针析构时默认进行 delete 释放资源,所以如果不是 new 出来的资源,交给智能指针管理会崩溃。智能指针支持在构造时给一个删除器,在它调用析构时会调用删除器去释放资源,这解决了不同 delete 的需求。

循环引用

循环引用问题出现在 shared_ptr 上,它会导致资源没有得到释放,内存泄漏,想要解决这个问题,需要用到 weak_ptr 。

先看例子:现在有 n1 和 n2 两个 shared_ptr:

假如 n1 的资源中又有一个shared_ptr 指针 _next 指向 n2,n2 的资源中又有一个shared_ptr 指针 _prev 指向 n1。注意此时计数器的变化:

当我们析构 n1 和 n2 时, 按理说资源应该被释放,但是 share_ptr 的资源释放是看的计数器释放为空,所以此时资源不会被释放:

这很显然并不符合实际需求,会导致内存泄漏。

weak_ptr 可以很好地解决这个问题。前面说过:weak_ptr 不支持 RAII 。它不支持绑定资源,只支持绑定 shared_ptr ,所以它不会增加 shared_ptr 的引用计数,我们将上面的 _next 和 _prev 指针设置为 weak_ptr 指针,就可以解决循环引用问题。

("来源:cplusplus.com")

weak_ptr 没有重载 operator* 和 operator-> 等,因为它不支持绑定资源,所以用它去访问资源是危险的,但它支持 expired 检查指向的资源是否过期,use_count 也可以获取 shared_ptr 的引用计数。weak_ptr 想访问资源时,可以调用 lock 返回一个管理资源的 shared_ptr ,如果资源已经被释放,返回的 shared_ptr 是一个空指针,如果没有释放,则通过返回的 shared_ptr 访问资源就行。

相关推荐
电子科技圈1 小时前
IAR作为Qt Group独立BU携两项重磅汽车电子应用开发方案首秀北京车展
开发语言·人工智能·汽车·软件工程·软件构建·代码规范·设计规范
代码中介商1 小时前
C语言指针深度解析:从数组指针到函数指针
c语言·开发语言
Jasmine_llq2 小时前
《B4356 [GESP202506 二级] 数三角形》
开发语言·c++·双重循环枚举算法·顺序输入输出算法·去重枚举算法·整除判断算法·计数统计算法
山栀shanzhi2 小时前
在做直播时,I帧的间隔(GOP)一般是多少?
网络·c++·面试·ffmpeg
止语Lab2 小时前
Go vs Java GC:同一场延迟战争的两条路
java·开发语言·golang
Rust研习社2 小时前
Rust 多线程从入门到实战
开发语言·后端·rust
Ulyanov2 小时前
《玩转QT Designer Studio:从设计到实战》 QT Designer Studio数据绑定与表达式系统深度解析
开发语言·python·qt
王老师青少年编程2 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【排序贪心】:魔法
c++·算法·贪心·csp·信奥赛·排序贪心·魔法
晓觉儿2 小时前
【GPLT】2026年第十一届团队程序设计天梯赛赛后题解(已写2h,存档中)
数据结构·c++·算法·深度优先·图论