C++03
std::auto_ptr
- 也许是它遭受初稿综合症的原件之一,仅提供有限的垃圾收集设施。第一个缺点是它要求delete
销毁,使它们无法用于保存数组分配的对象(new[]
)。它拥有指针的所有权,因此两个自动指针不应包含相同的对象。赋值将转移所有权并将右值自动指针重置为空指针。这可能导致最严重的缺点;由于上述无法复制,它们不能在 STL 容器中使用。对任何用例的最后打击是它们将在下一个 C++ 标准中被弃用。
std::auto_ptr_ref
- 这不是一个智能指针,它实际上是一个设计细节,用于std::auto_ptr
在某些情况下允许复制和分配。具体来说,它可用于使用 Colvin-Gibbons 技巧(也称为移动构造函数std::auto_ptr
)将非常量转换为左值以转移所有权。
相反,也许std::auto_ptr
并不是真的打算用作自动垃圾收集的通用智能指针。我的大部分有限理解和假设都是基于Herb Sutter 对 auto_ptr 的有效使用,我确实经常使用它,尽管并不总是以最优化的方式。
C++11
std::unique_ptr
- 这是我们的朋友,他将替换std::auto_ptr
它,这将是非常相似的,除了关键改进来纠正std::auto_ptr
使用数组、通过私有复制构造函数进行左值保护、可用于 STL 容器和算法等方面的弱点。因为它的性能开销并且内存占用有限,这是替换原始指针的理想候选者,或者更恰当地描述为拥有原始指针。正如“唯一”所暗示的那样,指针只有一个所有者,就像前一个一样std::auto_ptr
。
std::shared_ptr
- 我相信这是基于 TR1 的,boost::shared_ptr
但经过改进以包括别名和指针算法。简而言之,它将引用计数的智能指针包装在动态分配的对象周围。由于“共享”意味着当最后一个共享指针的最后一个引用超出范围时,指针可以由多个共享指针拥有,那么该对象将被适当地删除。这些也是线程安全的,并且在大多数情况下可以处理不完整的类型。std::make_shared
可用于std::shared_ptr
使用默认分配器有效地构造一个堆分配。
std::weak_ptr
- 同样基于 TR1 和boost::weak_ptr
。这是对 a 拥有的对象的引用,因此如果引用计数降至零std::shared_ptr
,则不会阻止删除该对象。std::shared_ptr
为了访问原始指针,您首先需要std::shared_ptr
通过调用访问,如果拥有的指针已过期并已被销毁lock
,它将返回一个空指针。std::shared_ptr
这主要用于在使用多个智能指针时避免无限期挂起的引用计数。
促进
boost::shared_ptr
- 可能在最多样化的场景(STL、PIMPL、RAII 等)中最容易使用,这是一个共享引用计数智能指针。在某些情况下,我听到了一些关于性能和开销的抱怨,但我一定忽略了它们,因为我不记得争论是什么了。显然,它已经流行到成为一个待定的标准 C++ 对象,并且没有想到有关智能指针的规范的缺点。
boost::weak_ptr
- 与前面的描述非常相似std::weak_ptr
,基于此实现,这允许对 a 的非拥有引用boost::shared_ptr
。毫不奇怪,您调用lock()
访问“强”共享指针并且必须检查以确保它是有效的,因为它可能已经被破坏了。只需确保不要存储返回的共享指针并在完成后立即让它超出范围,否则您将立即回到循环引用问题,您的引用计数将挂起并且对象不会被破坏。
boost::scoped_ptr
- 这是一个简单的智能指针类,开销很小,可能是为了更好地替代boost::shared_ptr
可用时而设计的。std::auto_ptr
尤其是在它不能安全地用作 STL 容器的元素或具有指向同一对象的多个指针这一事实时,它尤其具有可比性。
boost::intrusive_ptr
- 我从未使用过它,但据我了解,它旨在用于创建自己的智能指针兼容类。您需要自己实现引用计数,如果您希望您的类是通用的,您还需要实现一些方法,此外您还必须实现自己的线程安全。从好的方面来说,这可能为您提供了最自定义的方式来准确选择您想要多少或多少“智能”。intrusive_ptr
通常比它更有效,shared_ptr
因为它允许您为每个对象分配一个堆。(感谢阿维德)
boost::shared_array
- 这是一个boost::shared_ptr
数组。基本上new []
, operator[]
, 当然delete []
是烘焙的。这可以在 STL 容器中使用,据我所知,boost:shared_ptr
虽然你不能boost::weak_ptr
与这些容器一起使用,但一切都可以。但是,您也可以将 aboost::shared_ptr<std::vector<>>
用于类似功能并重新获得boost::weak_ptr
用于引用的能力。
boost::scoped_array
- 这是一个boost::scoped_ptr
数组。与boost::shared_array
所有必要的数组优点一样。这个是不可复制的,因此不能在 STL 容器中使用。我发现几乎任何你想使用它的地方你都可以使用std::vector
. 我从来没有确定哪个实际上更快或开销更少,但这个范围数组似乎比 STL 向量少得多。当您想在堆栈上保留分配时,请考虑boost::array
。
Qt
QPointer
- 在 Qt 4.0 中引入,这是一个“弱”智能指针,仅适用于QObject
派生类,在 Qt 框架中它几乎是所有东西,所以这并不是真正的限制。但是存在一些限制,即它不提供“强”指针,尽管您可以检查底层对象是否有效,但isNull()
您可以在通过检查后发现您的对象被销毁,尤其是在多线程环境中。我相信 Qt 人们认为这已被弃用。
QSharedDataPointer
- 这是一个“强”的智能指针,boost::intrusive_ptr
虽然它具有一些内置的线程安全性,但它确实需要您包含引用计数方法(ref
和deref
),您可以通过子类化来实现QSharedData
。与大部分 Qt 一样,对象最好通过充分的继承和子类化来使用,这似乎是预期的设计。
QExplicitlySharedDataPointer
- 非常相似,QSharedDataPointer
只是它没有隐式调用detach()
. 我将这个版本称为 2.0 版本,QSharedDataPointer
因为在引用计数降至零之后,关于何时分离的控制的轻微增加并不是特别值得一个全新的对象。
QSharedPointer
- 原子引用计数、线程安全、可共享指针、自定义删除(数组支持),听起来就像智能指针应该具备的一切。这是我在 Qt 中主要用作智能指针的东西,我发现它可以与boost:shared_ptr
Qt 中的许多对象相比,尽管开销可能要大得多。
QWeakPointer
- 你感觉到重复出现的模式了吗?就像std::weak_ptr
and boost::weak_ptr
this 与QSharedPointer
当您需要两个智能指针之间的引用时一起使用,否则会导致您的对象永远不会被删除。
QScopedPointer
- 这个名称也应该看起来很熟悉,实际上它boost::scoped_ptr
与 Qt 版本的共享指针和弱指针不同。它的功能是提供单个所有者智能指针,而不会产生开销,QSharedPointer
使其更适合兼容性、异常安全代码以及您可能使用std::auto_ptr
或boost::scoped_ptr
用于的所有事情。