是否有一种语言与RAII + Ref计数没有不安全的指针算术?

时间:2010-01-17 07:18:54

标签: c++ memory programming-languages raii

RAII =资源获取是初始化

Ref Counting =“穷人的GC”

在一起,它们非常强大(就像一个包含VBO的ref-counting 3D对象,它在调用析构函数时会抛出它)。

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

6 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:3)

虽然不完全是RAII,但Python有with statement而C#有using statement.

答案 2 :(得分:2)

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

Perl 5没有公开Perl代码的原始指针。

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

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

答案 3 :(得分:2)

perl,python(C),php和tcl是引用计数的,并且具有在引用计数变为零时销毁对象的机制,这可以在变量超出范围时立即发生。内置类型会自动释放。用户定义的类有一种方法可以定义在释放时调用的析构函数。

有一些边缘情况:全局变量可能直到结束时才会被释放,并且循环引用可能直到最后才被释放(尽管php最近实现了一个处理这种情况的gc并且python 2添加了一个循环检测器)。 / p>

答案 4 :(得分: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等)可能导致对象保持活动的资源。

答案 5 :(得分:1)

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

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