9

注意:对象生命周期 RAII 不使用/与块范围 RAII

似乎可以使用额外的 gc 类别、短期对象(经常检查 gc 类别)、长期对象(不经常检查 gc 类别)和资源对象(非常频繁地检查 gc 类别)。或者可能为资源对象使用额外的引用计数 gc。

似乎 using/with 风格可以通过提升 I/O 的功能性风格(如果我错了,这不是功能性风格,请原谅我)阻止大量 I/O 分散在这个地方与基于对象的 RAII 的灵活性(因为它更容易)。但是有些问题可能需要很难跟踪资源的生命周期。

除了避免 gc 的复杂性和速度之外,还有其他原因没有在主流语言上完成吗?(我知道有些语言在其主要实现中使用引用计数作为 gc 的一部分,因此,RAII 可能在那里工作,但我相信他们的规范没有为某些类型的对象/或所有对象指定引用计数,并且人们使用的其他实现没有引用计数,从而限制了这些语言中对象生命周期 RAII 的使用。

PS:他们在 perl 中有 c++ 类型的 RAII 吗?

4

1 回答 1

4

与传统的 C++ 相比,许多语言使编写自定义内部块处理器†</sup> 变得容易得多(这可能已在最新标准的当前草案中得到解决)。有了这些,使用 RAII 进行精确资源处理的要求就变得不那么紧迫了;你可以这样做:

using (Transaction t = makeTX()) {
    // blah
}

代替:

{
    Transaction t = makeTX();
    // blah
}

除了当您有多个嵌套using构造时,资源释放的顺序更清楚之外,实际上并没有太大的区别。(在引发异常的情况下,IMO 也更容易进行特殊处理,这对于您想要回滚错误的事务之类的事情很有用,但我不希望每个人都同意我的观点。)另请注意有许多不同的编写using结构的方式,其中一些比其他的更重量级,但我们真的不需要在这里探索不同之处。

鉴于以这种不同的方式处理精确的资源处理,对 C++ RAII 样式的需求要少得多,并且使用垃圾收集 (GC) 代替是可行的,因为它可以处理复杂的情况(即,任何难以处理的地方)将对象生命周期绑定到特定范围)更容易。公平地说,在某些情况下,您需要在不平凡的生命周期内进行精确的资源管理,但这些情况对每个人来说都是令人讨厌的

Perl 使用垃圾收集并具有廉价的子例程块,就像大多数其他脚本语言以一种或另一种形式一样(因为在脚本语言中代码和数据之间的划分比更传统的编译语言更松散)。我知道的唯一不使用 GC 的大型脚本语言是 Tcl,这是因为由于技术语义原因,那里的值系统保证无循环,因此引用计数就足够了。不过那里的代码块仍然便宜。

如果我们看一下主流编译语言(即,不是脚本语言),那么我们确实在 1990 年左右看到了分歧。在那之前的语言(包括 C++)往往不假设垃圾收集(除了一些例外,例如 Lisp、Smalltalk 和函数式编程语言),而此后的语言(尤其是 Java 和 C#)确实假设 GC。我想关于这一点有一个重大的哲学转变,可能与一些聪明的实现相结合,这些实现在此之前处理了 GC 中最令人震惊的问题。当您拥有 GC 时,您根本不会认为 RAII 是一种解决方案。它非常植根于 C++ 的世界模型。


†</sup> 我只是编造了这个词。

于 2010-10-09T06:54:21.913 回答