在阅读RAII,查看Herb Sutter's CppCon2014 presentation并阅读core guidelines和related articles之后的几天里,我仍然对所有权和相关语义。
假设A类和B类代表物理实体,并且有一个Scene类和一个Process类。如果可以,Process类是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指向,因为Process和Scene都有它们自己的A实例。B也会发生同样的情况,存储在a
和scn
中,并且正在处理 。那么为什么scn
不会make_unique
?
另一种方法是将所有内容都放在堆栈中(如代码片段中所示)。这两种解决方案对我来说似乎都是相同的,我完全不了解这两种选择的语义差异,但是我倾向于第一种。
答案 0 :(得分:3)
C ++所有权实质上可以归结为“谁负责删除这个特定对象,如果它们在这个特定时刻死亡”。在您的示例中,由于所有对象都有自动生存期,因此它们全部由Process::run
自己拥有。 add
,acquire
或release
中没有任何所有权转让。
现在,动态生命周期对象又如何处理呢?您的描述(我假设C
的意思是Scene
)仍然可以通过两种不同的方式实现:
Scene
拥有std::unique_ptr
的{{1}},这是给定的A
和Scene
可以将 {em> A
或std::unique_ptr
保留到std::shared_ptr
。可以通过上面概述的所有权的定义来做出第二个项目符号的选择。当B
握住A
而死亡时会发生什么?
B
也应死,那么B
是其唯一所有者,应通过A
持有std::unique_ptr
应该保留在B
内,则Scene
和Scene
都是所有者,并且都应通过{{ 1}} 这不包括非所有权(原始)指针,这很有用(例如,如果A
拥有B
,但std::shared_ptr
仍然需要直接引用,无论如何目的)。这些必须分别更新。