garbage-collection - 在 GC 语言中是否有关于(或更好地使用)RAII 的研究?

标签 garbage-collection using-statement raii with-statement object-lifetime

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

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

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

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

P.S.:他们在 perl 中有 c++ 类型的 RAII 吗?

最佳答案

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

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

代替:
{
    Transaction t = makeTX();
    // blah
}

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

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

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

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

† 我只是编造了这个词。

关于garbage-collection - 在 GC 语言中是否有关于(或更好地使用)RAII 的研究?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3685823/

相关文章:

python GC - 引用计数仅在 gc.collect() 时有效?

python - 更正扩展模块中的循环垃圾收集

c# - "using"方法内的语句会导致数据损坏或访问冲突的麻烦?

c++ - 如何处理未能释放包含在智能指针中的资源?

c++ - 如何将对象添加到 std::vector<unique_ptr<obj>>?

java - 设置-XX :+PerfDisableSharedMem JVM flag to false 的效果

java - 使用 Wea​​kHashMap 减少内存使用

使用给定类型和构造函数参数创建和销毁临时对象的 C++ 函数

vb.net - 在 Using 语句中通过工厂创建一次性对象

c++ - 使用专门的可变参数模板类的声明