18

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

但是,C++11 中还没有标准化的方法来分配原始内存块,您不必手动释放它。即使不调用析构函数,也有一些用例会有所帮助。一个例子是实现高效的并发数据结构(如 Herb Sutter 所提到的),而无需处理复杂的清理协议。

到现在为止还挺好。我的问题(从普通开发人员的角度,而不是 GC 库开发人员的角度):

有没有新的 C++11 GC 接口对您有所帮助的真实示例?

至少在我看来,世界没有改变。如果你需要 GC,你还是得找一个非标准的库,比如Boehm GC,学习如何集成和使用它。新的标准化接口在这方面不会有太大帮助。它也不会解决可移植性问题。

(从长远来看,C++11 标准定义的通用接口有望获得回报。但是,我的问题只针对近期。)

4

2 回答 2

10

不,目前没有C ++11 GC 接口的实际用途,因为同时没有完全支持此 API 的编译器。此外,C++11 标准将此 API 声明为可选,并且在主要编译器中没有看到实现它的动作(但正如 Jesse Good 指出的那样,MSVC 已经支持它)。

你也应该看看这篇文章,它有相关信息:为什么当 RAII 可用时进行垃圾收集?

于 2013-08-01T22:05:20.397 回答
2

std::shared_ptr提供所谓的引用计数垃圾收集。它实现起来很简单,但也有一些缺点。具体来说,它在许多应用程序中不如其他形式的垃圾收集效率低,更重要的是它不能处理循环引用。

Java 和 C# 被称为“托管语言”,而 C++ 被称为“非托管语言”,主要是因为它们实现了标记和清除垃圾收集。标记和清除垃圾收集处理循环引用。它通过在逻辑上搜索可达对象的图来做到这一点,然后定期删除那些不可达的对象。有更复杂的算法对此进行了优化(一种称为“世代”),但底层结构只是标记和清除。

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

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

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

于 2013-08-01T23:17:51.547 回答