c++ - 有实物表现的所有权

标签 c++ c++14 shared-ptr smart-pointers ownership

阅读 RAII 后,查看 Herb Sutter's CppCon2014 presentation ,并阅读 core guidelinesrelated articles在过去的几天里,我对所有权和相关语义仍然很困惑。

假设 A 类和 B 类代表物理实体,并且有一个 Scene 类和一个 Process 类。如果您愿意,Process 类是一个main 函数。在现实世界中,A 可以获得 B 并在物理上为自己保留它。它也可以释放它。因此,在 Process 实例的过程中,A 对象必须能够为自己拥有一个 B 实例,并且在完成它之后释放它。 A 和 B 生活在一个场景中,流程必须管理该场景。

B 也是派生的:A 使用一些接口(interface),而 Scene 使用 B 提供的其他接口(interface)。

让我们至少为流程尝试一些代码:

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++ 所有权本质上归结为“如果他们在这个特定时刻死亡,谁负责删除这个特定对象”。在您的示例中,由于所有对象都具有自动生命周期,因此所有对象都属于 Process::run 本身。 addacquirerelease 均不涉及所有权转移。

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

  • Scenestd::unique_ptr 保存到 A,这是给定的
  • SceneA 可以容纳任一个 std::unique_ptrstd::shared_ptr s 到 B

第二个项目符号中的选择可以通过我上面概述的所有权 定义来做出。当 A 拿着 B 死亡时会发生什么?

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

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

关于c++ - 有实物表现的所有权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53444116/

相关文章:

c++ - 将数据作为结构 vector 中的输入时的段错误 (SIGSEGV)

c++ - 迭代一个类的所有对象(但不是该类的父类 - C++)

c++ - 为什么这个右值引用绑定(bind)到左值?

c++ - 将自身从拥有它的容器中删除的shared_ptr,有更好的方法吗?

c++ - 如何有条件地将元素添加到 std::array - C++11

c++ - 从 DLL 访问 Windows CE .EXE 符号

c++ - 构造错误; VS2017 C++ 编译器回归?

c++ - SFINAE 优雅地检查 "template template class"(在模板参数中)

c++11 - 用 std::unique_ptr/std::shared_ptr 确认线程安全

c++ - 在 vector 中使用共享指针时发生内存泄漏