新闻中心

c++ 智能指针怎么用 c++ shared_ptr unique_ptr详解

2025-11-26
浏览次数:
返回列表
C++智能指针通过RAII机制自动管理内存,避免泄漏;std::unique_ptr独占所有权,不可复制但可移动,适用于单一所有者场景;std::shared_ptr采用引用计数实现共享所有权,支持多指针共享同一对象,析构时自动释放资源;为防止循环引用导致内存泄漏,应使用std::weak_ptr打破循环,其不增加引用计数,仅临时观察对象状态;推荐优先使用unique_ptr,共享时选用shared_ptr配合weak_ptr,并通过make_unique和make_shared创建以提升性能与安全。

c++ 智能指针怎么用 c++ shared_ptr unique_ptr详解

智能指针是 C++ 中用于自动管理动态内存的工具,能有效避免内存泄漏和资源泄露。它们通过 RAII(Resource Acquisition Is Initialization)机制,在对象生命周期结束时自动释放资源。C++ 标准库提供了 std::unique_ptrstd::shared_ptr 两种主要的智能指针类型,下面详细说明它们的用法和特点。

std::unique_ptr:独占式所有权

std::unique_ptr 表示对所指向对象的唯一所有权。同一时间只能有一个 unique_ptr 指向某个对象,不能复制,但可以移动。

适合用于“谁创建谁销毁”的场景,比如函数返回动态分配的对象、类成员管理资源等。

基本用法:
  • 使用 std::make_unique 创建(C++14 起推荐)
  • 析构时自动调用 delete
  • 不支持拷贝构造和赋值,但支持移动语义

示例:

#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(42);
    std::cout << *ptr << '\n'; // 输出 42

    // 移动所有权
    std::unique_ptr<int> ptr2 = std::move(ptr);
    // 此时 ptr 为空,ptr2 拥有对象

    if (!ptr) {
        std::cout << "ptr is null\n";
    }

    return 0;
}
注意事项:
  • 不要将同一个原始指针多次交给不同的 unique_ptr
  • 避免手动调用 release(),除非你清楚自己在做什么
  • 可以用自定义删除器处理非内存资源(如文件句柄)

std::shared_ptr:共享式所有权

std::shared_ptr 实现引用计数,多个 shared_ptr 可以共享同一个对象。当最后一个引用被销毁时,对象自动释放。

适用于需要多处访问同一资源的场景,比如缓存、观察者模式、树结构中的节点共享等。

Motiff妙多 Motiff妙多

Motiff妙多是一款AI驱动的界面设计工具,定位为“AI时代设计工具”

Motiff妙多 334 查看详情 Motiff妙多 基本用法:
  • 使用 std::make_shared 创建(更高效,推荐)
  • 内部维护引用计数,拷贝或赋值会增加计数
  • 析构时减少计数,为 0 时释放资源

示例:

#include <memory>
#include <iostream>

void func(std::shared_ptr<int> p) {
    std::cout << "In func: ref count = " << p.use_count() << '\n';
}

int main() {
    auto sp = std::make_shared<int>(100);
    std::cout << "ref count = " << sp.use_count() << '\n'; // 1

    {
        auto sp2 = sp; // 引用计数 +1
        std::cout << "ref count = " << sp.use_count() << '\n'; // 2
        func(sp2);     // 传参再 +1
    } // sp2 离开作用域,计数减回 1

    std::cout << "ref count = " << sp.use_count() << '\n'; // 1
    return 0;
}
性能提示:
  • make_shared 比直接 new 更快,因为它一次性分配控制块和对象内存
  • 频繁拷贝 shared_ptr 会有原子操作开销(线程安全)

避免循环引用:使用 weak_ptr

当两个 shared_ptr 相互持有对方时,会导致引用计数永不归零,造成内存泄漏。

解决方法是使用 std::weak_ptr —— 它不增加引用计数,只是临时观察对象是否存在。

示例:

#include <memory>
struct Node {
    std::shared_ptr<Node> parent;
    std::weak_ptr<Node> child; // 避免循环
};

auto node1 = std::make_shared<Node>();
auto node2 = std::make_shared<Node>();
node1->child = node2;
node2->parent = node1; // 正常引用
// 不会形成循环引用,node2 的 child 是 weak_ptr

访问 weak_ptr 前需检查是否有效:

if (auto p = weak_ptr.lock()) {
    // p 是 shared_ptr,可安全使用
} else {
    // 对象已释放
}

选择合适的智能指针

  • 大多数情况下优先用 unique_ptr:性能高、语义清晰
  • 需要共享所有权时用 shared_ptr
  • 配合 weak_ptr 打破循环引用
  • 尽量使用 make_uniquemake_shared,避免裸 new
基本上就这些。掌握这三种指针,就能写出安全高效的 C++ 内存管理代码。

以上就是c++++ 智能指针怎么用 c++ shared_ptr unique_ptr详解的详细内容,更多请关注其它相关文章!


# node  # c++智能指针  # 作用域  # 解决方法  # stream  # ios  # c++  # ai  # 工具  # 邯郸网站建设论坛官网  # 全国网站建设报价  # 网站推广效果预估怎么做  # 新闻源推广哪个网站好  # 广州个人网站建设  # 杭州seo推广很 好  # 浙江营销推广几种类型  # seo的培训学校  # 黑龙江网站推广制作公司  # 常州网站推广品牌有哪些  # 两种  # 句柄  # 多个  # 就能  # 会有  # 如何实现  # 内存管理  # 适用于  # 有什么  # red  # 标准库 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 如何在Promise链中有效终止错误处理后的执行  百度网盘网页版入口 百度网盘网页版官方登录网址  免费抖音短视频入口_抖音网页版短视频免费通道  提升屏幕阅读器对“m”时间单位的播报准确性:HTML与CSS组合解决方案  Safari自带网页翻译功能怎么用 无需插件轻松看懂外文网站【方法】  动漫岛观看全网网 动漫岛在线正版动漫入口  Golang如何处理RPC请求负载均衡_Golang RPC请求负载均衡策略与实践  HTML元素状态管理:根据DIV内容动态启用/禁用按钮  在J*a中如何隐藏复杂性_使用门面模式组织对象交互  在J*a中如何开发简易仓库管理与库存统计_仓库管理库存统计项目实战解析  天猫双十一预售商品怎么退款_天猫双十一预售退款操作指南  荣耀Play7T运行卡顿解决_荣耀Play7T性能优化  我的世界官方游戏入口 我的世界官网平台直达链接  深入理解Go语言中的指针类型:以*string为例  Go语言JSON解析深度指南:动态访问与结构体映射实践  在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析  Kafka Streams中基于消息头条件过滤消息的实现指南  腾讯QQ邮箱官方网站_QQ邮箱网页版在线登录  印象笔记如何设离线包出差查阅_印象笔记设离线包出差查阅【离线阅读】  c++如何使用chrono库处理时间_c++标准库时间与日期操作  J*aScript中安全有效地处理localStorage字符串数据  React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性  excel如何生成目录 excel一键生成工作表目录超链接  Bilibili动漫最新防封地址发布-Bilibili动漫2025年最稳正版入口推荐  解决Tabulator日期时间排序问题的专业指南  优化 Python 函数中的条件逻辑:解决 if-else 嵌套与参数选择问题  J*a 递归快速排序中静态变量的状态管理与陷阱  哔哩哔哩忘记密码了怎么找回_哔哩哔哩密码找回方法  天猫2025双十一0点秒杀攻略 天猫爆款抢购时间  LINQ to XML为何解析失败? 深入理解C# XDocument的异常处理  狙击外星人小游戏开始_狙击外星人小游戏立即开始  将HTML动态表格多行数据保存到Google Sheet的教程  C++如何解决segmentation fault_C++段错误调试与原因分析  vivo浏览器自带的下载器速度慢怎么办 vivo浏览器提升文件下载速度的技巧  Python实时数据流中的动态最值查找策略  PowerPoint如何制作滚动字幕结尾彩蛋_PowerPoint路径动画实现平滑滚动字幕效果  抖音DOU+怎么投最有效 抖音付费推广的ROI提升技巧  PDF怎么合并PDF并保持格式_PDF合并文件保持排版教程  解决Flask中Quill编辑器内容提交失败及TypeError的指南  一加Ace 6T实拍样张首次公布!李杰:主摄实力完全看齐4K档性能旗舰  J*aScript生成器_j*ascript异步迭代  移动端XML文件怎么转换成Excel 手机和平板上的解决方案  Yandex搜索引擎一键访问入口_俄罗斯Yandex官网免登录  qq音乐在线播放入口_qq音乐电脑版登录链接  漫蛙Manwa2官网入口地址分享 漫蛙漫画PC版永久访问通道  漫蛙2漫画入口 漫蛙正版网页漫画直达网址  Python中如何避免重复条件判断:利用数据结构实现动态逻辑  顺丰快递查单号物流信息 顺丰快递小程序查询入口  mysql如何设置表访问权限_mysql表访问权限配置  J*aScript中赋值与自增运算符的复杂交互与执行机制 

搜索