有实物表现的所有权
Ownership with a physical representation
阅读 RAII 后,查看 Herb Sutter's CppCon2014 presentation, and reading the core guidelines and related articles 这几天,我对所有权和相关语义仍然很困惑。
假设 class A 和 class B 代表物理实体,并且有一个场景 class 和一个过程 class。 Process class 是一个 main
函数,如果您愿意的话。在现实世界中,A 可以获得 B 并在物理上为自己保留它。它也可以释放它。因此,在 Process 实例的过程中,A 对象必须能够为自己拥有一个 B 实例,并且在完成它之后释放它。 As 和 Bs 生活在一个场景中,一个进程必须管理它。
也派生了B:A使用了一些接口,而Scene使用了B提供的其他接口。
让我们至少为流程尝试一些代码:
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
}
如果我错了,请在这里纠正我,这是可疑的部分。
据我了解,A 应该(而不是像代码那样)在堆上并从 shared_ptr 指向,因为进程和场景都有自己的 A 实例。相同B 会发生这种情况,它同时存储在 a
和 scn
中,并且 正在 中。为什么 scn
不是 make_unique
d?
另一种方法是将所有内容都放在堆栈上(就像在代码片段中一样)。这两个解决方案对我来说似乎是相同的,我根本不理解这两个选项的语义差异,但我倾向于第一个。
C++ 所有权基本上归结为 "who is responsible for deleting this particular object were they to die at this particular moment"。在您的示例中,由于所有对象都具有自动生命周期,因此所有对象都由 Process::run
本身拥有。 add
、acquire
或 release
.
均不涉及所有权转让
现在,动态生命周期对象的情况如何?您的描述(我假设 C
是指 Scene
)仍然可以通过两种不同的方式实现:
Scene
持有 std::unique_ptr
至 A
,这是给定的
Scene
和 A
可以容纳 std::unique_ptr
s 或 std::shared_ptr
s 到 B
.
第二个项目符号中的选择可以通过我在上面概述的 ownership 的定义来进行。当 A
拿着 B
死去时会发生什么?
- 如果
B
也死了,那么 A
是它的唯一所有者,应该通过 std::unique_ptr
持有它
- 如果
B
应该保留在 Scene
内,那么 Scene
和 A
都是所有者,并且都应该通过 a 持有 B
std::shared_ptr
这不包括非拥有(原始)指针,这可能很有用(例如,如果 A
拥有 B
但 Scene
仍然需要直接引用出于任何目的)。这些必须单独更新。
阅读 RAII 后,查看 Herb Sutter's CppCon2014 presentation, and reading the core guidelines and related articles 这几天,我对所有权和相关语义仍然很困惑。
假设 class A 和 class B 代表物理实体,并且有一个场景 class 和一个过程 class。 Process class 是一个 main
函数,如果您愿意的话。在现实世界中,A 可以获得 B 并在物理上为自己保留它。它也可以释放它。因此,在 Process 实例的过程中,A 对象必须能够为自己拥有一个 B 实例,并且在完成它之后释放它。 As 和 Bs 生活在一个场景中,一个进程必须管理它。
也派生了B:A使用了一些接口,而Scene使用了B提供的其他接口。
让我们至少为流程尝试一些代码:
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
}
如果我错了,请在这里纠正我,这是可疑的部分。
据我了解,A 应该(而不是像代码那样)在堆上并从 shared_ptr 指向,因为进程和场景都有自己的 A 实例。相同B 会发生这种情况,它同时存储在 a
和 scn
中,并且 正在 中。为什么 scn
不是 make_unique
d?
另一种方法是将所有内容都放在堆栈上(就像在代码片段中一样)。这两个解决方案对我来说似乎是相同的,我根本不理解这两个选项的语义差异,但我倾向于第一个。
C++ 所有权基本上归结为 "who is responsible for deleting this particular object were they to die at this particular moment"。在您的示例中,由于所有对象都具有自动生命周期,因此所有对象都由 Process::run
本身拥有。 add
、acquire
或 release
.
现在,动态生命周期对象的情况如何?您的描述(我假设 C
是指 Scene
)仍然可以通过两种不同的方式实现:
Scene
持有std::unique_ptr
至A
,这是给定的Scene
和A
可以容纳std::unique_ptr
s 或std::shared_ptr
s 到B
.
第二个项目符号中的选择可以通过我在上面概述的 ownership 的定义来进行。当 A
拿着 B
死去时会发生什么?
- 如果
B
也死了,那么A
是它的唯一所有者,应该通过std::unique_ptr
持有它
- 如果
B
应该保留在Scene
内,那么Scene
和A
都是所有者,并且都应该通过 a 持有B
std::shared_ptr
这不包括非拥有(原始)指针,这可能很有用(例如,如果 A
拥有 B
但 Scene
仍然需要直接引用出于任何目的)。这些必须单独更新。