小编典典

智能指针(升压)解释

all

以下一组指针有什么区别?你什么时候在生产代码中使用每个指针,如果有的话?

示例将不胜感激!

  1. scoped_ptr

  2. shared_ptr

  3. weak_ptr

  4. intrusive_ptr

你在生产代码中使用 boost 吗?


阅读 64

收藏
2022-06-07

共1个答案

小编典典

智能指针的基本属性

当您拥有可以分配每个智能指针的属性时,这很容易。有三个重要的属性。

  • 完全没有所有权
  • 所有权转让
  • 所有权份额

第一个意味着智能指针不能删除对象,因为它不拥有它。第二个意味着只有一个智能指针可以同时指向同一个对象。例如,如果要从函数返回智能指针,则所有权将转移到返回的智能指针。

第三个意思是多个智能指针可以同时指向同一个对象。这也适用于 原始指针 ,但是原始指针缺少一个重要特性:它们不定义它们是否 拥有
。如果每个所有者都放弃该对象,则所有权共享智能指针将删除该对象。这种行为恰好经常需要,因此共享拥有智能指针被广泛传播。

一些拥有智能指针既不支持第二个也不支持第三个。因此它们不能从函数返回或传递到其他地方。这最适合RAII智能指针保持本地并且刚刚创建以便在对象超出范围后释放对象的目的。

所有权共享可以通过复制构造函数来实现。这自然会复制一个智能指针,并且副本和原始指针都将引用同一个对象。所有权转移目前在 C++
中无法真正实现,因为没有任何方法可以将某物从一个对象转移到该语言支持的另一个对象:如果您尝试从函数中返回一个对象,那么会发生该对象被复制的情况。因此,实现所有权转移的智能指针必须使用复制构造函数来实现所有权转移。然而,这反过来又破坏了它在容器中的使用,因为需求声明了容器元素的复制构造函数的某种行为,这与这些智能指针的这种所谓的“移动构造函数”行为不兼容。

C++1x 通过引入所谓的“移动构造函数”和“移动赋值运算符”为所有权转移提供了原生支持。它还带有这样一个所有权转移智能指针,称为unique_ptr.

分类智能指针

scoped_ptr是一个既不可转让也不可共享的智能指针。如果您在本地需要分配内存,它只是可用的,但请确保它在超出范围时再次被释放。但如果您愿意,它仍然可以与另一个
scoped_ptr 交换。

shared_ptr是共享所有权的智能指针(上面的第三种)。它是引用计数的,因此它可以看到它的最后一个副本何时超出范围,然后释放管理的对象。

weak_ptr是一个非拥有的智能指针。它用于引用托管对象(由 shared_ptr 管理)而不添加引用计数。通常,您需要从 shared_ptr
中取出原始指针并复制它。但这并不安全,因为您无法检查对象何时被实际删除。因此,weak_ptr 通过引用由 shared_ptr
管理的对象来提供方法。如果您需要访问该对象,您可以锁定它的管理(以避免在另一个线程中一个 shared_ptr
在您使用该对象时释放它)然后使用它。如果weak_ptr 指向一个已经被删除的对象,它会通过抛出异常来通知你。当您有循环引用时,使用weak_ptr
是最有益的:引用计数无法轻松应对这种情况。

intrusive_ptr就像 shared_ptr 但它不会将引用计数保留在 shared_ptr
中,而是将计数的递增/递减留给需要由管理的对象定义的一些辅助函数。这样做的好处是已经引用的对象(其引用计数由外部引用计数机制递增)可以填充到
intrusive_ptr 中 - 因为引用计数不再是智能指针的内部,但智能指针使用现有的引用计数机制。

unique_ptr是一个所有权转移指针。您不能复制它,但可以使用 C++1x 的移动构造函数来移动它:

unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!

这是 std::auto_ptr 遵循的语义,但由于缺少对移动的本机支持,它无法为它们提供没有缺陷的。unique_ptr 将自动从临时的其他
unique_ptr 窃取资源,这是移动语义的关键特征之一。auto_ptr 将在下一个 C 标准版本中被弃用,取而代之的是
unique_ptr。C
1x 还将允许将只能移动但不能复制到容器中的对象填充。因此,例如,您可以将 unique_ptr
填充到向量中。如果您想了解更多关于此的信息,我将在这里停下来,并为您提供一篇关于此的精彩文章。

2022-06-07