单独所有权 vs 共同所有权的含义

21

在阅读维基百科关于 RAII 时,我看到了 SingleShared 所有权。

搜索了一下,但没有找到有用的答案!

能否有人为一个学生解释一下这个概念?


2
这个教程可能会有所帮助:http://www.daniweb.com/software-development/cpp/tutorials/378692/beginning-c0x-design-of-ownership。 - Mikael Persson
5个回答

31

这基本上是unique_ptrshared_ptr之间的比较。

单独所有权,也被称为唯一所有权,意味着资源由一个单个类实例拥有。一旦该实例停止存在,资源将通过析构函数释放。大多数RAII类都具有唯一所有权,例如std::vector

共享所有权意味着资源在多个类实例之间共享。只有在每个实例停止存在时才会释放资源,因此需要某种形式的引用计数或垃圾回收。您希望使用共享所有权的一个例子是处理非常昂贵且无法复制的不可变资源的句柄。我还看过它在图形中的使用。

想象一下指针可能会有所帮助。单独所有权将只有1个拥有指针,而共享所有权将具有多个指针。当然,RAII可能不涉及指针。

                    +---------------+
                    |Shared instance|
    +--------+      +------------+--+           +---------------+
    |Resource|                   |   +----------+Shared instance|
    +--------+                   v   v          +---------------+
        ^                    +--------+
        |                    |Resource|<-----------+
        |                    +--------+        +---+-----------+
        |                         ^            |Shared instance|
 +------+--------+                |            +---------------+
 |Unique Instance|                |
 +---------------+                |
                           +------+--------+
                           |Shared instance|
                           +---------------+

4
你用什么制作了那个图表? - Inisheer

8

所有权变量生命周期的概念紧密相关。

如果你能回答这个问题:这块内存什么时候可以被释放?,那么你就能解决所有权的问题。

如果这块内存只与一个变量的生命周期相关,那么它就具有单一所有权。

请注意,考虑动态分配和自动变量也很重要。对于自动变量,当其超出作用域时,与其相关的内存将被收回。而对于动态分配,通常情况下不会发生这种情况。如果你使用像std::unique_ptr<>这样的新工具实现单一所有权,那么当其超出作用域时,它所占用的动态内存就能自行清理。如果有许多引用指向该内存块,并且无法确定这些引用何时消失,则可能需要使用std::shared_ptr<>来实现多重所有权。


8
所有权归属于谁负责释放资源。通常,你可以说一部分代码(无论是函数还是类)是资源的唯一所有者。当它完成对资源的使用后,所有者必须释放它,以免资源泄漏。这被称为单一或独占所有权。
同样地,存在一个共享所有权的概念,其中两个或多个离散的代码部分(再次可以是类或函数)都依赖于相同的资源。在这种情况下,两者在资源不再需要时才能释放它。
C++提供了两个有用的包装器来传达和强制执行所有权语义 - 所有权语义就是上述所描述的内容。这些包装器泛化了RAII的概念 - 一旦超出范围,自动释放资源。
  • unique_ptr -- 当包含在独特指针中的对象超出范围时,即函数返回或类被销毁时,该对象将立即被释放。

  • shared_ptr -- 当包含在共享指针中的对象的所有“强引用”超出范围时,该对象仍然可用。这是一个称为引用计数的概念。一旦最后一个引用超出范围,资源就会被释放。

在像C++这样的语言中,所有权语义非常重要,因此我建议您了解现代C++如何传达和强制执行它。您可以从学习正确使用unique_ptrshared_ptr开始。


3

关于智能指针/RAII,共享所有权是指多个对象可以引用同一资源,只有在引用该资源的所有对象实例都被销毁时,该资源才会被释放。

// shared ownership

{
  std::shared_ptr<SomeClass> i(new SomeClass());
  {
    std::shared_ptr<SomeClass> j = i;

    {
      std::shared_ptr<SomeClass> k = j;

      // at this point i, j, k all own the same object

    }
    // k deconstructed and no longer shares ownership of the resource
  }
  // j deconstructed and no longer shares ownership of the resource
}
// i deconstructed and he resource is also released / free'd

在共享(唯一)所有权中,所有权要么随着物体的消失而消失,要么传递给另一个物体。

// single/unique ownership

{
  std::unique_ptr<SomeClass> i(new SomeClass());
  {
    std::unique_ptr<SomeClass> j = std::move(i); // k takes ownership of the object from i
  }
  // j is deconstructed and the resource is also released / free'd
}
// i deconstructed and nothing is released, as the ownership already passed to j

最后一个使用unique_ptr的示例是错误的 - 因为unique_ptr的复制构造函数是私有的,那将无法编译。如果改用std::move(),则可以编译。 - Andy

2

单一所有权意味着当所有者完成对资源的使用后,应将其删除。

如果是共享所有权,则不能删除它,因为其他所有者可能仍在使用它!因此,资源删除必须通过某种方式进行协调,通常通过引用计数来实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接