具有实物代表的所有权 [英] Ownership with a physical representation
问题描述
在阅读RAII之后,查看 Herb Sutter的CppCon2014演示文稿,然后阅读< a href = http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-sharedptrparam-const rel = nofollow noreferrer>核心指南和相关 文章几天来,我仍然对所有权和相关语义感到困惑。
假设类A和类B代表物理实体,并且有一个Scene类和一个Process类。如果愿意,Process类是一个 main
函数。在现实世界中,A可以获取B并实际保留它。它也可以释放它。因此,在Process实例的过程中,A对象必须能够拥有一个B实例,并且必须在完成该实例后将其释放。
也派生了B:A使用某些接口,而Scene使用B提供的其他接口。 。
让我们至少为该过程尝试一些代码:
class Process
{
public:
void run();
};
void Process :: run()
{
auto scn = Scene {};
auto a = A {};
auto b = B {};
scn.add(a); //存储
scn.add(b); //存储b
a.acquire(b); //存储b,并表示B的实际拥有权
a.doSomething();
a.release(b); //将a的B实例设置为null,然后实际丢失B
}
纠正我
据我了解,A应该(而不是像代码一样)放在堆上并从一个shared_ptr,因为Process和Scene都有它们自己的A实例。B也会发生同样的情况,它存储在 a
和 scn
,并且正在处理 。为什么为什么 scn
不是 make_unique
d?
另一种方法是将所有内容都放在堆栈上(如代码段中所示)。这两种解决方案对我来说似乎都是相同的,我根本不了解这两种选择的语义差异,但是我倾向于第一种。
C ++所有权实质上可以归结为谁负责删除此特定对象,如果它们在此特定时刻死亡。在您的示例中,由于所有对象都具有自动生存期,因此它们全部由 Process :: run
本身拥有。 添加
,获取
或发行版$ c $均不涉及所有权转让c>。
现在,动态生命周期对象又如何处理呢?您的描述(我假设 C
您的意思是场景
)仍然可以通过两种不同的方式实现:
-
场景
持有std :: unique_ptr
s到A
,这是给定的 -
Scene
和A
可以容纳std :: unique_ptr
s或std: :shared_ptr
到B
。
可以通过上面概述的所有权定义来选择第二个项目符号。当 A
死于并持有 B
时会发生什么?
- 如果
B
也应死,那么A
是其唯一所有者,并且应该通过std :: unique_ptr
保留它,如果
B
应该保留在场景
中,然后 Scene
和 A
都是所有者,并且都应通过 std :: shared_ptr
这不包括非所有者(原始)指针,这可能会很有用(例如,如果 A
拥有一个 B
,但出于任何目的,场景
仍需要直接引用)。这些必须分别更新。
After reading on RAII, viewing Herb Sutter's CppCon2014 presentation, and reading the core guidelines and related articles over the course of some days, I'm still quite confused on ownership and related semantics.
Let's say class A and class B represent physical entities, and there's a Scene class and a Process class. The Process class is a main
function, if you will. In the real world, an A can acquire a B and physically keep it for itself. It can also release it. During the course of a Process instance, an A object must therefore be able to have for itself a B instance, and also to release it after it's done with it. As and Bs live in a Scene, which a Process must manage.
Also B is derived: an A uses some interface, while a Scene uses some other interface a B provides.
Let's try with some code for at least the Process:
class Process
{
public:
void run();
};
void Process::run()
{
auto scn = Scene {};
auto a = A {};
auto b = B {};
scn.add(a); // stores a
scn.add(b); // stores b
a.acquire(b); // stores b, and represents physical possession of a B
a.doSomething();
a.release(b); // sets a's B instance to null, and physically loses the B
}
Correct me here if I'm wrong, this is the dubious part.
From what I understand, A should (instead of like the code) be on the heap and pointed to from a shared_ptr, since the Process and the Scene both have their own instance of A. The same would happen for B, which is stored both in a
and in scn
, and which is in process. Why would then scn
not be make_unique
d?
The other way to do this is have everything on the stack (like in the code snippet). Both solutions seem identical to me, I don't understand the semantic difference of these two options at all, but I would tend to the first one.
C++ ownership essentially boils down to "who is responsible for deleting this particular object were they to die at this particular moment". In your example, as all objects have automatic lifetime, all of them are owned by Process::run
itself. There's no ownership transfer involved in any of add
, acquire
or release
.
Now, what about the same thing with dynamic-lifetime objects? Your description (where I assume by C
you mean Scene
) can be implemented in two different ways still:
Scene
holdsstd::unique_ptr
s toA
's, that's a givenScene
andA
can hold eitherstd::unique_ptr
s orstd::shared_ptr
s toB
.
The choice in the second bullet can be made through the definition of ownership I outlined above. What happens when and A
dies while holding a B
?
- If the
B
should die as well, thenA
is its sole owner and should hold it viastd::unique_ptr
- If the
B
should remain inside theScene
, thenScene
andA
are both owners, and should both hold theB
through astd::shared_ptr
This doesn't include non-owning (raw) pointers, which can be useful (for example, if A
owns a B
but Scene
still needs a direct reference for whatever purpose). These must be updated separately.
这篇关于具有实物代表的所有权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!