gpt4 book ai didi

c++ - RAII 是否支持资源所有权转移?

转载 作者:行者123 更新时间:2023-12-03 23:58:32 24 4
gpt4 key购买 nike

我过去主要认为 RAII 是关于使用对象生命周期来避免资源泄漏,这在实践中对我很有用。但是我最近讨论了什么是 RAII 模式,什么不是,这让我在网上搜索了更多的定义和评论,结果增加了更多的困惑而不是清晰。
RAII 类的标准定义似乎需要两个属性:

  • RAII 类的构造函数应该获取资源或在该过程中失败时抛出异常。
  • RAII 类的析构函数应该释放资源。

  • 但后来我也看到在一些 RAII 定义中提到资源所有权可以在此类 RAII 类的实例之间“安全转移”。因此,资源所有权转移似乎被接受为 RAII 模式的一部分。
    但是,资源所有权转移似乎也导致打破似乎定义 RAII 的那两个属性。
    假设我有两个 RAII 类的实例 - Instance_SourceInstance_Destination - 并且我从 Instance_Source 转移了基础资源的所有权至 Instance_Destination .然后我们有:
  • 与属性 2 的冲突:
  • Instance_Source的析构函数不会释放任何资源,所以我们现在打破了析构函数应该释放资源的要求。

  • 与属性 1 的冲突:
  • 在初始化中获取资源的优点之一是我可以使用知道它们包含有效资源的实例(否则它们不会被构造)。但是随着所有权转移,我现在剩下的实例不再包含有效资源,这消除了在构造函数中获取资源应该带来的主要优势。
  • 也有我不想要的场景Instance_Destination在它的构建过程中获取任何资源,因为我希望它只获得什么的所有权 Instance_Source获得,在特殊条件下。为了支持这样的场景,我必须打破构造函数获取资源的要求,以允许初始化 Instance_Destination无需获取任何资源。


  • 因此,在我需要允许资源所有权转移的情况下,我发现我必须“松散”处理关于在构造函数中获取资源并在析构函数中释放它们的 2 RAII 要求。这在实践中运作良好,但它是否仍然构成理论上的 RAII 模式?
    这就是我提出问题的原因: RAII 是否支持资源所有权转移?
    如果答案是 ,那么看起来大多数 RAII 定义应该重新设计,不依赖于构造函数和析构函数应该对资源做什么。
    如果答案是 ,那么这应该被强调为 RAII 的一个重要限制。

    最佳答案

    Does RAII support resource ownership transfer?


    可以,是的。

    But then it seems that resource ownership transfer also leads to breaking those very 2 properties that seem to define RAII.


    有点取决于人们如何定义 RAII 的细节。

    解决方案是扩展问题中显示的 RAII 的定义,以允许表示空状态。如果有空状态的表示,则可以通过将源 RAII 对象保留在这种空状态来移动资源的所有权。
    构建和销毁问题中给出的定义对此进行调整是微不足道的:
  • 构造要么获取资源,要么初始化为空状态。从技术上讲,这不是必需的,但如果允许空状态,则允许默认构造很方便。
  • 析构函数释放资源当且仅当它拥有任何资源。
  • 如前一段所述的移动的附加定义。

  • 标准库中的大多数 RAII 类都有空状态的表示,并且那些支持传输它们的资源。此类 RAII 类及其空状态的典型示例:
  • 任何动态容器 - 不包含任何元素(并且有空容量)的容器
  • 任何智能指针 - 空值
  • std::fstream - 与文件无关的流
  • std::thread - 与线程无关的包装器

  • 标准库也有 RAII 类,它们没有空状态的表示,因此不能支持资源的传输。此类的一个示例是 std::lock_guard .

    I wish someone could also provide a historical perspective


    我所拥有的定义的最古老来源是 Stroustrup 的书“C++ 编程语言第 3 版”。根据维基百科的估计,RAII 是在 1984-89 年左右开发的,所以到这本书出版时,它已经是一个 8-13 岁的想法。以下是最相关的部分,希望不会侵犯版权:

    14.4.1 Using Constructors and Destructors

    The technique for managing resources using local objects is usually referred to as "resource acquisition is initialization." This is a general technique that relies on the properties of constructors and destructors and their interaction with exception handling.

    ...

    A constructor tries to ensure that its object is completely and correctly constructed. When that cannot be achieved, a well-written constructor restores - as far as possible - the state of the system to what it was before creation.


    14.4.2 Auto_ptr

    ... auto_ptr, which supports the "resource acquisition is initialization" technique.


    鉴于 std::auto_ptr不一定拥有资源,因此它的析构函数在这种情况下不会释放资源,它可以将资源转移到另一个实例,创造RAII的作者认为 std::auto_ptr “支持 RAII”,我有信心说与问题中描述的属性冲突并不会取消 RAII 的资格。
    请注意,std::auto_ptr 已被 C++11 中移动语义的引入所淘汰,此后已从语言中删除。

    E.3.5.3 Delaying resource acquisition

    ... resources should be acquired in constructors whenever delayed resource acquisition isn't mandated by the semantics of a class.


    我没有发现关于 RAII 如何与转移资源所有权的能力相关的明确描述。我怀疑在为具有移动语义的语言编写的后续版本中可能会更多地讨论它。

    关于c++ - RAII 是否支持资源所有权转移?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66395016/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com