具有实物代表的所有权 [英] Ownership with a physical representation

查看:189
本文介绍了具有实物代表的所有权的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读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 您的意思是场景)仍然可以通过两种不同的方式实现:




  • 场景持有 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
    B
    >

    这不包括非所有者(原始)指针,这可能会很有用(例如,如果 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_uniqued?

    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 holds std::unique_ptrs to A's, that's a given
    • Scene and A can hold either std::unique_ptrs or std::shared_ptrs to B.

    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, then A is its sole owner and should hold it via std::unique_ptr
    • If the B should remain inside the Scene, then Scene and A are both owners, and should both hold the B through a std::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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆