C++ 智能指针
C++ 智能指针
auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被c++11弃用。所以我只说后3个。
C++ 标准库智能指针
使用这些智能指针作为将指针封装为纯旧 C++ 对象 (POCO) 的首选项。
-
unique_ptr
只允许基础指针的一个所有者。 除非你确信需要 shared_ptr,否则请将该指针用作 POCO 的默认选项。 可以移到新所有者,但不会复制或共享。 替换已弃用的 auto_ptr。 与 boost::scoped_ptr 比较。 unique_ptr 小巧高效;大小等同于一个指针且支持 rvalue 引用,从而可实现快速插入和对 C++ 标准库集合的检索。 头文件:<memory>
。 有关详细信息,请参阅如何:创建和使用 unique_ptr 实例和 unique_ptr 类。 -
shared_ptr
采用引用计数的智能指针。 如果你想要将一个原始指针分配给多个所有者(例如,从容器返回了指针副本又想保留原始指针时),请使用该指针。 直至所有 shared_ptr 所有者超出了范围或放弃所有权,才会删除原始指针。 大小为两个指针;一个用于对象,另一个用于包含引用计数的共享控制块。 头文件:<memory>
。 有关详细信息,请参阅如何:创建和使用 shared_ptr 实例和 shared_ptr 类。 -
weak_ptr
结合 shared_ptr 使用的特例智能指针。 weak_ptr 提供对一个或多个 shared_ptr 实例拥有的对象的访问,但不参与引用计数。 如果你想要观察某个对象但不需要其保持活动状态,请使用该实例。 在某些情况下,需要断开 shared_ptr 实例间的循环引用。 头文件:<memory>
。 有关详细信息,请参阅如何:创建和使用 weak_ptr 实例和 weak_ptr 类。
auto_ptr、unique_ptr和shared_ptr这几个智能指针背后的设计思想:
将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。
unique_ptr
unique_ptr不共享指针。 它不能复制到另一个 unique_ptr函数,由值传递给函数,或在任何需要复制副本的 C++ 标准库算法中使用。 只能移动 unique_ptr。 这意味着,内存资源所有权将转移到另一 unique_ptr,并且原始 unique_ptr 不再拥有此资源。 我们建议你将对象限制为由一个所有者所有,因为多个所有权会使程序逻辑变得复杂。 因此,当需要纯 C++ 对象的智能指针时,请使用make_unique帮助程序函数。
unique_ptr 在 C++ 标准库的标头中
unique_ptr 是一个独享所有权的智能指针,它提供了严格意义上的所有权,包括:
-
拥有它指向的对象
-
无法进行复制构造,无法进行复制赋值操作。即无法使两个unique_ptr指向同一个对象。但是可以进行移动构造和移动赋值操作
-
保存指向某个对象的指针,当它本身被删除释放的时候,会使用给定的删除器释放它指向的对象
shared_ptr
shared_ptr 类型是 C++ 标准库中的一个智能指针,是为多个所有者可能必须管理对象在内存中的生命周期的方案设计的。 在您初始化一个 shared_ptr 之后,您可复制它,按值将其传入函数参数,然后将其分配给其他 shared_ptr 实例。 所有实例均指向同一个对象,并共享对一个“控制块”(每当新的 shared_ptr 添加、超出范围或重置时增加和减少引用计数)的访问权限。 当引用计数达到零时,控制块将删除内存资源和自身。
weak_ptr
weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。
最佳设计是避免在任何时候都能实现指针的共享所有权。 但是,如果您必须有实例的 shared_ptr 共享所有权,请避免它们之间存在循环引用。 如果无法避免循环引用,或者出于某种原因更可取,则使用 weak_ptr 向一个或多个所有者提供对另 shared_ptr 一个的弱引用。 通过使用 weak_ptr ,可以创建一个 shared_ptr 联接到一组现有相关实例的,但前提是基础内存资源仍有效。 weak_ptr本身并不参与引用计数,因此它无法阻止引用计数转到零。 但是,你可以使用 weak_ptr 来尝试获取用于初始化的的新副本 shared_ptr 。 如果已删除内存,则的 bool 运算符将 weak_ptr 返回 false 。 如果内存仍有效,新的共享指针会递增引用计数,并保证只要 shared_ptr 变量保持在范围内,内存就有效。weak_ptr是弱智能指针对象,它不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的智能指针。将一个weak_ptr绑定到一个shared_ptr对象,不会改变shared_ptr的引用计数。一旦最后一个所指向对象的shared_ptr被销毁,所指向的对象就会被释放,即使此时有weak_ptr指向该对象,所指向的对象依然被释放。
如何选择智能指针
-
如果程序要使用多个指向同一个对象的指针,应选择shared_ptr。这样的情况包括:
- 有一个指针数组,并使用一些辅助指针来标示特定的元素,如最大的元素和最小的元素;
- 两个对象包含都指向第三个对象的指针;
- STL容器包含指针。很多STL算法都支持复制和赋值操作,这些操作可用于shared_ptr,但不能用于unique_ptr(编译器发出warning)和auto_ptr(行为不确定)。如果你的编译器没有提供shared_ptr,可使用Boost库提供的shared_ptr。
-
如果程序不需要多个指向同一个对象的指针,则可使用unique_ptr。如果函数使用new分配内存,并返还指向该内存的指针,将其返回类型声明为unique_ptr是不错的选择。这样,所有权转让给接受返回值的unique_ptr,而该智能指针将负责调用delete。可将unique_ptr存储到STL容器在那个,只要不调用将一个unique_ptr复制或赋给另一个算法(如sort())。
-
基于性能考虑:
-
unique_ptr独占对象的所有权,由于没有引用计数,因此性能较好
-
shared_ptr共享对象的所有权,但性能略差
-
weak_ptr配合shared_ptr,解决循环引用的问题
由于性能问题,那么可以粗暴的理解:优先使用unique_ptr。但由于unique_ptr不能进行复制,因此部分场景下不能使用的。
-
https://www.cnblogs.com/sunsky303/p/16497592.html
https://cloud.tencent.com/developer/article/2101824
https://blog.csdn.net/cpp_learner/article/details/118912592
https://learn.microsoft.com/zh-cn/cpp/cpp/smart-pointers-modern-cpp?view=msvc-170
https://stibel.icu/md/guide/c++-overview.html#c-基础
https://stibel.icu/md/guide/c++-overview.html#c-基础
https://stibel.icu/md/c++/basic/c++-basic-oop.html
https://learn.microsoft.com/zh-cn/cpp/cpp/cpp-language-reference?view=msvc-170
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY