6

RAII = 资源获取即初始化

参考计数=“穷人的GC”

它们一起非常强大(就像一个引用计数的 3D 对象持有一个 VBO,当它的析构函数被调用时它会抛出释放)。

现在,问题是——除了 C++ 之外,RAII 是否存在于任何语言中?特别是,不允许指针算术/缓冲区溢出的语言?

4

6 回答 6

3

D 有 RAII 但仍然有指针算术 :( 但是,你真的不必使用它。请注意让 D 工作对我来说是一件痛苦的事,所以我只是说。

于 2010-01-17T07:23:52.973 回答
3

虽然不完全是 RAII,但 Python 有with 语句,而 C# 有using 语句。

于 2010-01-17T08:14:31.580 回答
2

Perl 5 具有引用计数和析构函数,当所有引用超出范围时保证会调用它们,因此 RAII 在该语言中可用,尽管大多数 Perl 程序员不使用该术语。

并且 Perl 5 不公开指向 Perl 代码的原始指针。

然而,Perl 6 有一个真正的垃圾收集器,实际上允许关闭垃圾收集器;所以你不能依赖以任何特定顺序收集的东西。

我相信 Python 和 Lua 使用引用计数。

于 2010-01-17T07:34:09.597 回答
2

perl、python (C)、php 和 tcl 是引用计数的,并且一旦对象的引用计数变为零就会销毁对象,一旦变量超出范围,就会发生这种情况。内置类型会自动释放。用户定义的类有一种方法来定义将在发布时调用的析构函数。

有一些边缘情况:全局变量可能要到最后才释放,循环引用可能要到最后才释放(尽管 php 最近实现了一个 gc 来处理这种情况,python 2 添加了一个循环检测器)。

于 2010-01-17T07:56:45.707 回答
2

Python(标准 CPython,而不是 Jython、Unladen Swallow 和 IronPython 等变体)对其对象使用引用计数。

有了它,它还具有 RAII 和(大部分)确定性垃圾收集。例如,这应该可以确定性地关闭文件:

def a():
   fp = open('/my/file', 'r')
   return fp.read()

注意fp.close()永远不会被调用。一旦fp超出范围,对象就应该被销毁。但是,在某些情况下不能保证确定性最终确定,例如:

  • 某些东西抛出异常并且当前正在处理回溯,或者保留对它的引用(注意sys.last_traceback保留最后的回溯)
  • 对象中存在循环引用,导致引用计数不归零

因此,虽然 python 理论上具有确定性终结,但最好显式关闭任何可能异常(如 IOError 等)可能导致对象保持活动的资源。

于 2010-01-17T07:59:30.070 回答
1

Vala的对象内存管理基于引用计数,并且它具有 RAII(在某种意义上,它的析构函数被确定性地调用)。典型的用例是创建 GUI,其中引用计数的开销通常可以忽略不计。您可以使用指针并绕过引用计数,例如为了互操作性,或者如果您需要额外的性能,但在大多数情况下,您可以在没有指针的情况下生活。它还做了一些聪明的事情,您可以将引用标记为ownedorunowned并转移所有权,并且在许多情况下,它能够省略引用计数(例如,如果对象没有转义函数)。Vala 与 GObject/GTK 密切相关,因此只有在您想在该生态系统中工作时才有意义。

另一个有趣的候选者是Rust。虽然它也有指针和垃圾收集,但两者都是可选的。您可以完全使用与 C++ 的智能指针等效的程序编写程序,保证没有泄漏,并且它支持 RAII。它也有一个引用所有权的概念,就像 Vala,但有点复杂。从本质上讲,Rust 让您可以完全控制管理内存的方式。您可以在裸机级别工作,甚至可以在其中编写内核,或者您可以在高级别的 GC 上工作,或者介于两者之间的任何东西,并且大多数情况下它可以保护您免受内存或其他指针泄漏 -相关的错误。缺点是它非常复杂,而且由于它仍在开发中,事情可能会发生变化。

于 2014-07-05T12:10:21.107 回答