单一与共享所有权的含义
Posted
技术标签:
【中文标题】单一与共享所有权的含义【英文标题】:single vs shared ownership meaning 【发布时间】:2012-11-30 22:07:09 【问题描述】:刚刚看到Single
和Shared
所有权时正在阅读RAII 的***。
用谷歌搜索,找不到任何有用的答案!
有人可以为小学生解释这个概念吗?
【问题讨论】:
This tutorial 可能会有所帮助。 【参考方案1】:本质上是unique_ptr
vs shared_ptr
。
单一所有权,也称为唯一所有权,表示资源由一个单一类实例拥有。一旦该实例不再存在,资源就会被释放(通过析构函数)。您发现的大多数 RAII 类都有唯一的所有权,例如 std::vector
。
共享所有权意味着资源在多个类实例之间共享。只有在每个实例不再存在时才会释放资源,因此需要某种形式的引用计数或垃圾收集。您希望共享所有权的一个例子是一个非常昂贵的复制不可变资源的句柄。我也看到它在图表中使用过。
从指针的角度思考可能会有所帮助。单一所有权将只有 1 个拥有指针,共享将有多个。当然,RAII 可能不涉及指针。
+---------------+
|Shared instance|
+--------+ +------------+--+ +---------------+
|Resource| | +----------+Shared instance|
+--------+ v v +---------------+
^ +--------+
| |Resource|<-----------+
| +--------+ +---+-----------+
| ^ |Shared instance|
+------+--------+ | +---------------+
|Unique Instance| |
+---------------+ |
+------+--------+
|Shared instance|
+---------------+
【讨论】:
你用什么来制作这张图?【参考方案2】:所有权与可变生命周期的概念密切相关。
如果你能回答这个问题,这块内存什么时候可以消失?,那么你就可以回答所有权问题了。
如果那块内存只与一个变量的生命周期相关联,那么您拥有单一所有权。
请注意,考虑堆或动态分配与堆栈或自动变量也很重要。使用自动变量,当它们超出范围时,与它们相关的内存就会被回收。对于动态分配,一般情况下并非如此。如果您为单一所有权使用诸如 std::unique_ptr 之类的新工具,那么您可以让一块动态内存在超出范围时自行清理。如果有很多对该内存块的引用,并且这些引用何时消失的顺序不确定,那么您可能需要像 std::shared_ptr 这样的东西来获得多重所有权。
【讨论】:
【参考方案3】:所有权归结为谁负责释放资源。通常,您可以说代码的一部分(无论是函数还是类)是资源的唯一所有者。当资源完成后,所有者将不得不为资源释放它而不是leak。这称为单一或unique 所有权。
同样,存在shared 所有权的概念,其中两个或多个离散的代码部分(再次它们可以是类或函数)都依赖于相同的资源。在这种情况下,两者都必须不再需要资源才能释放它。
C++ 提供了两个有用的包装器来传达和执行所有权语义——所有权语义就是上面所描述的。这些包装器概括了RAII 的概念——一旦资源超出范围就会自动释放。
unique_ptr
-- 包裹在唯一指针中的对象将在超出范围时立即被释放,这意味着函数返回或类被销毁。
shared_ptr
-- 包装在共享指针中的对象将保持可用,直到所有“强引用”都超出范围。这是一个称为reference counting 的概念。一旦最终引用超出范围,资源就会被释放。
所有权语义在 C++ 等语言中非常重要,因此我建议您熟悉 现代 C++ 如何传达和执行它。你可以从学习unique_ptr
和shared_ptr
的正确用法开始。
【讨论】:
【参考方案4】:关于智能指针/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() 那么它将编译。【参考方案5】:单一所有权意味着当所有者用完一个资源后,它应该删除它。
如果它是共享所有权,那么它不能删除它,因为其他所有者可能仍在使用它!因此,资源删除必须通过某种方式进行协调,通常是通过引用计数。
【讨论】:
以上是关于单一与共享所有权的含义的主要内容,如果未能解决你的问题,请参考以下文章
java并发编程中的“可变变量”一词与函数式编程中的含义相同吗?