news 2026/6/15 19:43:32

【C++ 】智能指针:内存管理的 “自动导航仪”

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【C++ 】智能指针:内存管理的 “自动导航仪”

【C++】智能指针:内存管理的“自动导航仪”

在现代 C++(C++11 及以后)中,智能指针是管理动态内存最推荐、最安全的方式。
它们的核心目标是:

  • 自动释放内存(RAII 思想)
  • 防止内存泄漏
  • 避免悬垂指针
  • 减少手动delete的出错概率

C++ 标准库提供了三种主要智能指针,它们各有明确的使用场景和权衡。

一、智能指针家族对比表(强烈建议背下来)

智能指针类型头文件所有权语义是否可拷贝是否可移动主要使用场景开销线程安全
std::unique_ptr<T><memory>独占所有权资源唯一拥有者、工厂函数返回值、Pimpl极低(几乎无)
std::shared_ptr<T><memory>共享所有权需要多个对象共享同一资源、容器元素较高(引用计数)否(计数器线程安全)
std::weak_ptr<T><memory>弱引用(不拥有)打破shared_ptr循环引用、缓存、观察者极低(不增计数)

二、三大智能指针详解与使用规范

1. std::unique_ptr(独占所有权,最轻量)

特点

  • 同一时刻只有一个unique_ptr拥有资源
  • 不可拷贝,只能移动(std::move
  • 析构时自动delete指向的对象
  • 开销几乎为零(通常只占一个指针大小)

最常见用法

#include<memory>#include<iostream>classResource{public:~Resource(){std::cout<<"资源被销毁\n";}};intmain(){// 方式1:推荐的现代写法autoptr=std::make_unique<Resource>();// C++14+// 方式2:显式构造(C++11)std::unique_ptr<Resource>p1(newResource());// 转移所有权(非常重要)autop2=std::move(p1);// p1 变为空,p2 获得所有权// 访问if(p2){// 使用 *p2 或 p2.get()}// 离开作用域自动销毁}

常用场景

  • 工厂函数返回值
  • RAII 封装文件句柄、socket、锁等
  • Pimpl 模式(私有实现)
  • 作为类成员(独占资源)

注意
不要用new后直接赋值给unique_ptr裸指针变量,会导致双重释放风险。

错误示范:

Resource*raw=newResource();std::unique_ptr<Resource>p1(raw);std::unique_ptr<Resource>p2(raw);// 灾难!双重 delete

正确示范:

autop1=std::make_unique<Resource>();autop2=std::move(p1);
2. std::shared_ptr(共享所有权,引用计数)

核心机制引用计数(reference counting)

  • 每个shared_ptr内部维护两个指针:
    • 指向实际对象的原始指针
    • 指向控制块的指针(存放引用计数、删除器、弱引用计数等)

创建方式对比(非常重要):

// 不推荐(异常不安全)std::shared_ptr<T>p(newT());// 推荐(异常安全,性能更好)autop=std::make_shared<T>();// C++11 起,最推荐

引用计数变化规则

操作强引用计数变化弱引用计数变化对象是否销毁
shared_ptr拷贝构造/赋值+1
shared_ptr析构-1计数为0时销毁
weak_ptr构造+1
weak_ptr析构-1
weak_ptr::lock()成功+1

经典使用场景

  • 多个对象需要共享同一份资源
  • 放入容器(如vector<shared_ptr<T>>
  • 树形结构、图结构中的节点共享

循环引用问题(经典面试题):

structNode{std::shared_ptr<Node>next;~Node(){std::cout<<"销毁\n";}};intmain(){auton1=std::make_shared<Node>();auton2=std::make_shared<Node>();n1->next=n2;n2->next=n1;// 循环引用!两个对象都不会被销毁}

解决办法:用weak_ptr打破环

structNode{std::weak_ptr<Node>next;// 改为 weak_ptr};
3. std::weak_ptr(观察者,不拥有所有权)

核心作用

  • 不增加强引用计数
  • 不会阻止对象的析构
  • 可通过lock()尝试转换为shared_ptr
  • 常用于缓存、观察者模式、打破循环引用

典型用法

std::shared_ptr<int>sp=std::make_shared<int>(42);std::weak_ptr<int>wp=sp;if(autolocked=wp.lock()){std::cout<<*locked<<"\n";// 42}else{std::cout<<"对象已销毁\n";}

三、现代 C++ 智能指针最佳实践总结

  1. 优先使用std::make_unique/std::make_shared
  2. 需要共享所有权才用shared_ptr
  3. 独占资源一律用unique_ptr
  4. weak_ptr解决循环引用或临时观察
  5. 永远不要把new得到的裸指针直接存到多个智能指针中
  6. 容器中存储对象指针时,优先考虑shared_ptrunique_ptr
  7. 不要在函数参数中使用shared_ptr传参(除非明确需要共享所有权)
    • 正确:void func(const Widget&)void func(Widget*)
    • 不推荐:void func(std::shared_ptr<Widget>)(除非函数要保存一份)

四、常见面试高频问题

  1. unique_ptrshared_ptr的区别?
  2. 为什么make_sharedshared_ptr(new T)更好?
  3. weak_ptr有什么用?如何检测对象是否还活着?
  4. 什么是循环引用?如何用智能指针解决?
  5. shared_ptr的控制块包含什么信息?
  6. unique_ptr能否拷贝?如何转移所有权?

如果你想继续深入某个部分,例如:

  • 自定义删除器(deleter)
  • enable_shared_from_this用法与原理
  • shared_ptrweak_ptr实现原理(控制块结构)
  • 智能指针在多线程中的正确用法
  • 经典手撕题目:实现简易shared_ptr

随时告诉我,我可以继续展开详细讲解或代码实现。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 18:20:24

实测才敢推 8个AI论文平台:本科生毕业论文写作全维度测评

对于高校学生&#xff0c;尤其是本科生而言&#xff0c;毕业论文写作是一项既重要又复杂的任务。从选题构思到文献检索&#xff0c;从大纲搭建到内容撰写&#xff0c;再到格式调整和查重修改&#xff0c;每一个环节都可能成为“卡脖子”的难题。随着AI技术的不断成熟&#xff0…

作者头像 李华
网站建设 2026/6/15 18:19:39

【CSDN观察】高新技术企业认定的意义在于解决三个核心矛盾

其深刻意义&#xff0c;在于解决了中国科技型企业在特定发展阶段面临的 三个核心矛盾&#xff1a;一、 解决“野蛮生长”与“可持续发展”的矛盾&#xff1a;从机会驱动到体系驱动初创企业依靠创始人的技术直觉和市场机会&#xff08;即文件中的“个人经验”&#xff09;得以存…

作者头像 李华
网站建设 2026/6/14 22:14:37

【含文档+PPT+源码】基于小程序开发的宠物寄养平台管理系统

项目介绍本课程演示的是一款基于小程序开发的宠物寄养平台管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料2.带你从零开始部署运行本套系统3.该项目附…

作者头像 李华
网站建设 2026/6/15 15:33:13

CANN shmem 在多模型共驻场景下的安全隔离架构

相关链接&#xff1a; CANN 组织主页&#xff1a;https://atomgit.com/cannshmem 仓库地址&#xff1a;https://atomgit.com/cann/shmem 前言 在 CANN&#xff08;Compute Architecture for Neural Networks&#xff09;高性能通信生态中&#xff0c;SHMEM&#xff08;Shared …

作者头像 李华
网站建设 2026/6/15 16:39:53

【Matlab】MATLAB 图形绘制教程:hold on 保留图形用法详解(同图多曲线绘制与多组数据对比)

MATLAB 图形绘制教程:hold on 保留图形用法详解(同图多曲线绘制与多组数据对比) 在MATLAB数据可视化中,plot函数是绘制二维曲线的核心工具,但默认情况下,每次调用plot函数都会清空当前图形窗口,覆盖之前绘制的曲线,无法实现“同一张图中绘制多条曲线”的需求。而hold …

作者头像 李华
网站建设 2026/6/14 4:59:55

【Matlab】MATLAB 多子图绘制教程:subplot 用法详解

MATLAB 多子图绘制教程:subplot 用法详解 在MATLAB数据可视化与文档编辑中,单一图形往往无法满足多组数据对比、多维度结果展示的需求。subplot函数作为MATLAB绘制多子图的核心工具,能够实现“在同一个图形窗口中,分割出多个独立的绘图区域,分别绘制不同曲线或图形”,完…

作者头像 李华