商城首页欢迎来到中国正版软件门户

您的位置:首页 >C++智能指针是什么?如何选择?

C++智能指针是什么?如何选择?

  发布于2026-03-16 阅读(0)

扫一扫,手机访问

std::unique_ptr适用于独占所有权场景,移动后原指针为空,零开销;std::shared_ptr用于共享所有权,有引用计数开销和循环引用风险;std::weak_ptr仅观察对象存续,需lock()判空使用;禁用std::auto_ptr和裸new/delete。

C++中的智能指针(Smart Pointers)是什么?(如何选择)

std::unique_ptr 适合“独占所有权”的场景

它表示资源只能被一个指针持有,移动后原指针自动变空——这是最轻量、零开销的智能指针。用在需要明确生命周期边界的地方,比如函数返回新对象、容器里存动态对象、RAII 资源封装。

常见错误是试图拷贝 std::unique_ptr:编译器会直接报错 use of deleted function,这不是 bug,是设计使然。别硬加 .get() 再手动 new,那等于放弃智能指针的价值。

实操建议:

  • 构造时优先用 std::make_unique(...),避免裸 new
  • 传参用 const std::unique_ptr&(只读)或按值移动(转移所有权)
  • 放进 std::vector 没问题,但别用 std::shared_ptr 去接它的 .get(),会 double-delete

std::shared_ptr 的引用计数不是免费的

它靠原子计数支持多所有者共享,但每次拷贝、赋值、析构都要操作计数器,还额外分配控制块(control block),内存和性能开销比 std::unique_ptr 明显更高。

典型误用是“图省事全用 shared_ptr”:比如局部变量、短生命周期对象、不需要跨作用域共享的场合。结果是缓存不友好、分配碎片多、调试时发现对象死活不释放(循环引用)。

实操建议:

  • 只在真正需要共享所有权时用,例如观察者模式里的回调持有、对象图中多入口访问
  • 警惕循环引用:两个 std::shared_ptr 互相持有对方,得用 std::weak_ptr 打断
  • 创建时也优先用 std::make_shared(...),它能把对象和控制块一次分配,比先 new 再包更高效

std::weak_ptr 不是“弱引用”,而是“非拥有型观察者”

它不增加引用计数,只用来观察 std::shared_ptr 管理的对象是否还活着。不能直接解引用,必须调用 .lock() 转成 std::shared_ptr 才能安全使用。

常见错误是把 std::weak_ptr 当成“可空的 shared_ptr”来用,或者在 .lock() 后不检查返回值就直接 *ptr——这时如果原对象已销毁,.lock() 返回空 std::shared_ptr,解引用会崩溃。

实操建议:

  • 专用于打破循环引用:A 持有 B 的 std::shared_ptr,B 用 std::weak_ptr 回指 A
  • 缓存、监听器列表等需“临时借用”对象的场景,避免延长生命周期
  • 每次 .lock() 后必须判空:if (auto p = wp.lock()) { /* use *p */ }

不要用 std::auto_ptr(已移除)、也不要裸 new + delete

std::auto_ptr 在 C++11 就被删了,它的拷贝语义是“转移”,极易引发静默悬空指针。现在所有主流标准库(GCC、Clang、MSVC)都不再支持它,代码里出现就是编译错误。

new/delete 最大的坑不是写错,而是异常安全:构造中途抛异常,delete 就永远不会执行。哪怕你写了 try/catch,也难覆盖所有路径。

实操建议:

  • 看到 std::auto_ptr,立刻换成 std::unique_ptr,接口基本一致,语义清晰
  • 任何需要动态分配的地方,先想“谁负责释放”,再选对应智能指针类型;没想清楚就先卡住
  • 第三方 API 要求裸指针?用 .get() 提供地址,但别交出所有权;要交出,用 .release() 并确保对方真会 delete

所有权模型看着简单,实际踩坑多在边界模糊处:比如 lambda 捕获智能指针时用值还是引用、容器里放指针还是对象、跨线程传递要不要 std::shared_ptr。这些地方没有银弹,得看数据流和生命周期图。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注