【问题标题】:Can lazy loading be considered an example of RAII?可以将延迟加载视为 RAII 的示例吗?
【发布时间】:2012-09-27 15:30:48
【问题描述】:

在 iOS 上独家使用 Objective-C 几年后,我最近一直在追赶我的 c++,而“新风格”c++ 上出现最多的话题是 RAII

为了确保我正确理解 RAII 概念,您是否会将 Objective-C 延迟加载属性访问器视为一种 RAII?比如检查下面的访问方式

- (NSArray *)items {
    if(_items==nil) {
        _items=[[NSArray alloc] initWithCapacity:10];
    }
    return _items
}

这会被视为 RAII 的一个例子吗?如果不是,你能解释一下我错在哪里吗?

【问题讨论】:

  • 你为什么认为延迟加载会成为 RAII 的一个元素?
  • 我猜是因为我显然不太了解 RAII :)
  • 这是一个完全合法的问题,我只是说让这个问题对每个人都更有帮助,包括你头脑中的推理。就像问题一样,“葡萄柚是气候变化的一个因素吗?”这将有助于解释您认为的联系是什么。
  • 好吧,我认为 RAII 主要是为了确保资源在您“获取”它后就可以使用,哪种延迟加载有点像,也许类似?但是知道我知道RAII不一样,我错了

标签: c++ objective-c lazy-loading raii meta


【解决方案1】:

RAII 不幸被广泛滥用。

最初的概念Resources Acquisition Is Initialization就是使用构造函数来保证事情的发生。在这个想法中:

std::fstream out("somefile.txt", "w");

应该保证如果out被创建过,那么该文件存在并且可以使用。

因此,延迟加载与 RAII 是相反的

注意:不过,如今,RAII 主要用于指代自动清理。一个例子是智能指针。离最初的目标有点远。


关于清理,另一个成语是 SBRM,用于 Scoped Bound Resources Management。但是,它并没有完全捕捉到确定性清理的概念。 SBRM 的想法是保证当某个对象超出范围时将清理资源。例如,这可以通过boost::scoped_ptr 来实现。

但是这无法捕捉到 unique_ptr 所做的事情,因为您实际上可以 returnunique_ptr 从而让资源逃离它创建的范围!

【讨论】:

  • 延迟加载与 RAII 正好相反! 这不是真的。对于调用者来说,RAII 对象可以整天延迟加载,调用者不需要知道。在您的示例中,我认为 RAII 并不意味着文件是立即创建的。这只意味着如果没有概念上创建和初始化对象就不能存在。所以它基本上禁止像InitLoadCreate这样的方法。换句话说,说他们是对立的给他们一种不存在的关系。在某些情况下它们会发生冲突,但总的来说它们只是不相关的概念。
  • @tenfour:我同意延迟加载可能会使这对用户透明,但是如果延迟加载失败,你如何处理它?用户确定拥有该资源,而您未能获得!举一个引人注目的例子,想想互斥锁。使用 RAII,构建锁定对象可以保证我锁定了互斥体,因此我可以安全地继续做我的事情。现在假设你决定延迟加载,我获取互斥锁上的锁,做一些不可撤销的事情,并使用触发锁的延迟加载的“锁定”项......并且生成了一个异常。哎呀?
  • 这可能取决于您对“资源”一词的应用程度。但是如果构造函数没有实际上获取打开的文件描述符,那么就像Matthieu所说,资源获取不是初始化,资源获取是可以在以后任何时间发生的事情(因此以后的任何事情都可能由于资源获取失败而失败)。 tenfour 所说的“在概念上创建文件”可以描述为“建立一个简单的类不变量”(也许:它知道它所指的文件名)。它可能会获得 a 资源(例如复制名称),但不会获得 the 资源。
  • ...所以我认为 Matthieu 是对的,懒惰地打开文件是对他所描述的该术语的原始含义的滥用。这根本不是滥用该术语的当前含义,而只是因为新含义并不要求资源获取和初始化之间应该有任何关系。相反,RAII 的当前含义要求资源释放是破坏。如果对象一旦“拥有”资源,则在获取资源时完全无关紧要。
  • 好点,这让这个问题更加有趣。
【解决方案2】:

虽然首字母缩略词命名为初始化,但成语的重点是破坏。 Resource Acquisition Is Initialization更多的是关于Scoped Bound Resource Management,即让对象管理资源并在超出范围时将其清除。

【讨论】:

    【解决方案3】:

    不,一点也不。此外,“新型 C++”是指“至少在过去 15 年里,每个人都在做这件事”。

    RAII 涉及自动存储持续时间的对象,在它们的析构函数中清理动态对象,这些对象属于它们。所有权的确切时间无关紧要。

    【讨论】:

    • 我想我比我当时想的还要过时:)
    【解决方案4】:

    没有; RAII 是一些具有动态存储的对象被包装在具有自动存储的对象中,并在具有自动存储的对象被销毁时被销毁。

    延迟加载(仅在您真正需要时才加载对象,而不是之前加载)和 RAII 并没有真正的关系。

    【讨论】:

      猜你喜欢
      • 2017-03-22
      • 1970-01-01
      • 2018-04-02
      • 2011-08-25
      • 2013-06-06
      • 2012-04-05
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      相关资源
      最近更新 更多