有实物表现的所有权

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 会发生这种情况,它同时存储在 ascn 中,并且 正在 中。为什么 scn 不是 make_uniqued?

另一种方法是将所有内容都放在堆栈上(就像在代码片段中一样)。这两个解决方案对我来说似乎是相同的,我根本不理解这两个选项的语义差异,但我倾向于第一个。

C++ 所有权基本上归结为 "who is responsible for deleting this particular object were they to die at this particular moment"。在您的示例中,由于所有对象都具有自动生命周期,因此所有对象都由 Process::run 本身拥有。 addacquirerelease.

均不涉及所有权转让

现在,动态生命周期对象的情况如何?您的描述(我假设 C 是指 Scene)仍然可以通过两种不同的方式实现:

  • Scene 持有 std::unique_ptrA,这是给定的
  • SceneA 可以容纳 std::unique_ptrs 或 std::shared_ptrs 到 B.

第二个项目符号中的选择可以通过我在上面概述的 ownership 的定义来进行。当 A 拿着 B 死去时会发生什么?

  • 如果 B 也死了,那么 A 是它的唯一所有者,应该通过 std::unique_ptr
  • 持有它
  • 如果 B 应该保留在 Scene 内,那么 SceneA 都是所有者,并且都应该通过 a 持有 B std::shared_ptr

这不包括非拥有(原始)指针,这可能很有用(例如,如果 A 拥有 BScene 仍然需要直接引用出于任何目的)。这些必须单独更新。