C++11的垃圾回收ABI有实际用途吗?

18

C++11引入了与垃圾收集器交互的接口。据我所见,它提供了一种标准化的方式来与GC进行通信(例如declare_no_pointers),并获取关于如何处理伪装指针的信息(例如get_pointer_safety)。

然而,在C++11中,尚未有一种标准化的方式来分配原始内存块,这样就不必手动释放。即使不调用析构函数,也有一些使用情况会有所帮助。一个例子是实现高效的并发数据结构(Herb Sutter所提到的)而无需处理复杂的清理协议。

到目前为止,还不错。我的问题(从普通开发者的角度出发,而不是GC库开发者的角度):

是否有真实世界的例子表明新的C++11 GC接口对您有所帮助?

至少从我的角度来看,世界没有改变。如果你需要GC,仍然需要寻找一个非标准库,例如Boehm GC,并学习如何集成和使用它。新的标准化接口在这方面帮助并不大,也无法解决可移植性问题。
(长期来看,C++11标准定义的通用接口有望产生作用。但是,我的问题只针对即时未来。)

6
据我所知,任何编译器都不支持这个。 - Rapptz
1
@Rapptz: Clang和gcc不支持它,但是msvc支持。 - Jesse Good
7
我可能会被一小部分声音很大的人所攻击,但是谁会想在C++中使用垃圾回收机制呢?我们已经拥有了RAII,在C++语义方面这比GC有更好的效果。不过,不可否认的是,在其他不具备同样期望的语言中它可能会很有用 - 比如我是一个大的Lisp粉丝,我无法想象没有GC的Lisp。 - syam
2
@syam 让我来支持你。除了糟糕的算法之外,垃圾回收是快速程序的最大敌人。 - user529758
@H2CO3 有趣的是,我的评论并没有引起我担心的骚动。我想我错了,认为它是有争议的。(太好了,我喜欢在这种情况下错) :) - syam
@syam 有争议吗?你在谈论C++。那些想要GC的人可能只是不太了解这门语言,不敢回复你的评论而已。 - Christian Rau
2个回答

10

目前没有任何实际使用C++11 GC接口的方法,因为目前没有一款编译器完全支持此API。此外,C++11标准将此API声明为可选项,并且没有看到在主要编译器中实现它的运动(但正如Jesse Good所指出的,MSVC已经支持它)。

此外,您应该查看这篇文章,它包含相关信息:为什么在RAII可用时需要垃圾收集?


谢谢提供链接。这是我发现有用的另一个相关答案:http://stackoverflow.com/questions/10578627/whats-the-timeline-of-a-gc-implementation-in-mainstream-c-compilers/10578761#10578761 - Philipp Claßen

2

std::shared_ptr提供了所谓的引用计数垃圾回收机制。它很容易实现,但有一些缺点。具体而言,在许多应用程序中,它比替代形式的垃圾回收效率低,并且更重要的是,它不能处理循环引用。

Java和C#被称为“托管语言”,而C++被称为“非托管语言”,主要是因为它们实现了标记-清除垃圾回收机制。标记-清除垃圾回收机制可以处理循环引用。它通过逻辑地搜索可达对象图,然后定期删除不可达对象来实现这一点。还有更复杂的算法对此进行了优化(其中一个称为“分代”),但基本结构仍然是标记-清除。

在C++中实现标记-清除的问题在于,有很多操作使得跟踪对象图变得困难。 “安全派生指针”概念旨在将这些问题分离出来并定义,以便我们可以说哪些功能可以用于维护GC对对象图的视图的完整性。然后,编译器应该能够静态地识别和诊断违反这些规则的结构(重新解释转换,指针算术等)。

那些声称“为什么需要垃圾回收当你有RAII时”是困惑的。 RAII是一种可能的内存模型,它使用所有权概念。每个对象必须由恰好一个其他对象拥有,并且该所有者负责其生命周期。对于许多对象模型,这根本不是自然或方便的,因为一个对象被几个其他对象引用,而没有明确的所有者。对于许多应用程序,您希望在对象变得无法引用时自动结束其生命周期,这就是Java和C#“默认情况下”的工作方式。

我认为新的内存模型和“安全派生对象”概念应该会导致真正的可选标记-清除垃圾回收器在标准库中提供。这样的功能将非常受欢迎 - 但我认为它还没有实现。 “安全派生对象”内容是未来发展的基础。


4
Java和C ++被称为“受控语言”,而C ++则被称为“非受控语言”。这只是微软为区分.NET语言和本机语言而创建的术语:http://en.wikipedia.org/wiki/Managed_code - Manu343726
1
@user1131467 只是挑剔一下,但现在M&S正在逐步淘汰...代际GC变得更加普遍,而良好的引用计数(+循环消除)正在获得越来越多的关注,尤其是在托管内存区域越大时(为了改善局部性)。 - syam
1
@syam: 分代GC是标记和清除的一种优化形式。分代只是意味着您假设对象已经可以访问了很长时间,并且在大多数情况下仍然可以访问。逻辑效果和所需的对象图信息与标记和清除相同。引用计数与循环消除不兼容,因此我不确定您的意思是什么(您能提供“赢得关注”的引文吗?)。引用计数最常见但罕见的情况是实时应用程序,在这些应用程序中,随机停止进行垃圾回收是不可接受的。 - Andrew Tomazos
@user1131467 引用计数法在循环消除中绝对是兼容的,即使在并行非停止GC中也是如此--参见Bacon等人的研究。关于“获得动力”的部分,这可能尚未在主流实现中使用,但随着RAM大小的增加,选择很少:使用M&S会有太多的高速缓存崩溃,几乎没有其他解决方案可以将局部性保持在最小限度。 (有趣的是,Python使用引用计数+循环消除,但由于其大型解释器锁定而几乎没有价值)。预计很快会看到更多的引用计数GC... - syam
1
@Alex:正如我在帖子中所述,引用计数被认为是一种垃圾收集形式,即使它的简单形式不会收集循环引用。 - Andrew Tomazos
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接