当前位置: 首页 > news >正文

C++ 智能指针 std::unique_ptr、std::shared_ptr、std::weak_ptr

C++ 智能指针 std::unique_ptr、std::shared_ptr、std::weak_ptr

  • 1. std::unique_ptr、std::shared_ptr、std::weak_ptr的区别
    • 1.1 设计目的区别
    • 1.2 与原始指针区别
    • 1.3 常见陷阱
  • 2. 典型使用场景举例
    • 2.1 std::unique_ptr —— 独占所有权(推荐默认选择)
    • 2.2 std::shared_ptr —— 多个对象共享资源
    • 2.3 std::weak_ptr —— 弱引用(观察者或防循环)

1. std::unique_ptr、std::shared_ptr、std::weak_ptr的区别

C++ 智能指针是现代 C++(尤其是 C++11 以后)资源自动管理(RAII) 的核心工具之一。它主要用于自动管理动态内存(new 出来的对象),避免手动 delete 引发的内存泄漏或悬空指针问题。

📌 经验法则:

  • 先用 unique_ptr,除非确实需要共享。
  • 不要在容器中放原始裸指针。
  • 如果 shared_ptr 出现循环引用,就用 weak_ptr。

💬 「独占用 unique_ptr,共享用 shared_ptr,观察用 weak_ptr。」

1.1 设计目的区别

三种智能指针的主要类型及核心区别

智能指针头文件所有权模型使用场景是否可共享是否可转移是否允许空常见误区
std::unique_ptr<T><memory>独占所有权资源唯一拥有者(如工厂、资源管理类)❌ 否✅ 可通过 std::move 转移不能复制,只能移动
std::shared_ptr<T><memory>共享所有权(引用计数)多个对象需共享同一资源(如图节点、缓存)✅ 是循环引用会导致内存泄漏
std::weak_ptr<T><memory>弱引用(不计数)打破 shared_ptr 循环引用,或非拥有观察者✅(依赖 shared_ptr)使用前必须 lock()

核心思想与使用意图

指针类型设计目的类比理解
unique_ptr资源由单个对象独占管理。生命周期严格定义。「唯一所有者」——像独居房主,别人不能进。
shared_ptr多个对象共同使用同一资源,由引用计数控制释放时机。「合租房」——最后一个人搬走时才退房。
weak_ptr避免循环引用或监控资源是否还存在。「访客」——只看房,不拥有。

性能与选择建议

需求建议指针
资源唯一(默认情况)unique_ptr
多个模块需共享资源shared_ptr
避免循环引用或仅做观察weak_ptr
原始指针管理复杂资源❌ 避免,优先智能指针

1.2 与原始指针区别

项目原始指针 T*智能指针(如 unique_ptr
内存释放手动 delete自动析构
所有权明确所有权
拷贝语义浅拷贝根据类型控制(禁止或共享)
异常安全容易泄漏RAII 自动管理
性能最快有轻微开销(shared_ptr)

1.3 常见陷阱

错误用法原因与后果
shared_ptr 管理同一裸指针两次会导致重复释放
unique_ptr 获取裸指针长期保存生命周期不安全
shared_ptr 相互引用循环引用,内存不释放
混用 newmake_shared性能和安全问题,推荐 make_shared / make_unique

2. 典型使用场景举例

2.1 std::unique_ptr —— 独占所有权(推荐默认选择)

#include <memory>
#include <iostream>struct Data { Data() { std::cout << "create\n"; }~Data() { std::cout << "destroy\n"; }
};void process(std::unique_ptr<Data> p) {std::cout << "processing...\n";
}int main() {auto ptr = std::make_unique<Data>();process(std::move(ptr));  // 所有权转移// 此处 ptr 已为空
}

✅ 优点:

  • 无额外引用计数开销
  • 最快
  • 最安全(资源唯一)

🚫 缺点:不能共享,不能复制

2.2 std::shared_ptr —— 多个对象共享资源

#include <memory>
#include <iostream>struct Node {std::shared_ptr<Node> next;~Node() { std::cout << "Node destroyed\n"; }
};int main() {auto a = std::make_shared<Node>();auto b = std::make_shared<Node>();a->next = b;b->next = a; // ❌ 循环引用,永不释放!
}

✅ 优点:

  • 方便多个模块/对象共享同一资源

🚫 缺点:

  • 引用计数性能开销
  • 容易出现循环引用 → 内存泄漏
  • 构造、析构相对较慢

🧩 解决循环引用:

struct Node {std::weak_ptr<Node> next; // 改为 weak_ptr
};

2.3 std::weak_ptr —— 弱引用(观察者或防循环)

#include <memory>
#include <iostream>struct A {std::shared_ptr<A> child;std::weak_ptr<A> parent; // 弱引用避免循环
};int main() {auto root = std::make_shared<A>();auto child = std::make_shared<A>();root->child = child;child->parent = root; // 不增加引用计数
}

✅ 优点:

  • 可观察但不控制生命周期
  • 打破 shared_ptr 循环引用

🚫 缺点:访问前要 lock() 检查有效性:

if (auto p = child->parent.lock()) {// p 有效
}
http://www.dtcms.com/a/507637.html

相关文章:

  • 猿辅导Java面试真实经历与深度总结(三)
  • Doris 数据导入
  • 网站建设+泰安saas建站平台有哪些
  • 动态规划之两个字符组/两个数组的dp问题
  • 【AI论文】UniVideo:面向视频的统一理解、生成与编辑
  • 获取resources目录下静态资源的两种方式
  • 一个域名可以做几个网站吗最好加盟网站建设
  • Android 自定义 View 如何设置默认尺寸
  • C#技术栈
  • 广东建设监理网站如何查企业的工商信息
  • INT301 Bio-computation 生物计算(神经网络)Pt.2 监督学习模型:感知器(Perceptron)
  • 机器学习(4)多特征与向量化
  • stripe/paypal
  • 机器学习(5)特征缩放与梯度下降收敛
  • 英飞凌推出首款100V aec合格GaN晶体管
  • 李宏毅机器学习笔记27
  • 机器学习作业七
  • openEuler安装jdk,nginx,redis
  • ffmpeg 交叉编译
  • Python编程之面向对象
  • 建设一个网站大概费用门户网站开发工具
  • OpenCV cv::Mat.type() 以及类型数据转换
  • Elasticsearch批量写入50万数据
  • 爬取GitHub开源项目信息并生成词云:从数据抓取到可视化实践
  • 做阀门的网站域名有了怎么建设网站
  • 西安交大Nat. Commun:749.276 cm²认证效率19.50%,通过IEC测试迈向产线
  • 百度站长平台登录网站图片自动轮换怎么做的
  • KuiklyUI 科普:UI 如何映射到 Android View 并完成渲染
  • 【2025-系统规划与管理师】第11章:信息系统治理
  • Python中如何实现数据库迁移