2

有谁知道支持垃圾收集的 C++ 编译器。我知道他们正在为 c++11 考虑它,但没有实现它。

4

2 回答 2

6

最常听到的方法之一是使用 Hans Boehm 的 GC,它可以插入 C++。当然,另一种方法是使用智能指针来跟踪对象的使用。

对于支持“谁需要这个”评论的每个人,答案是它可能更贵:

  • 想象一下,你 fork() 程序现在开始调整对象中的引用计数器,否则这些对象保持不变。这将导致性能开销,因为这意味着操作系统无法在两个进程之间共享内存,即它破坏了写时复制。在某些情况下,这可能意味着操作系统只需要在内存中进行交换以复制和调整引用计数器。
  • 另一个示例类似于建议的boost::shared_ptr. 这些中的每一个都有额外的分配作为开销,以便存储引用计数器、弱引用计数器和删除器。这也不是免费的。此外,其实例具有指针大小的两倍。
  • 然后,如果您使用普通 size_t 作为 refcounter 和内置增量/减量,您的代码不是多线程安全的。但是,如果您使用原子整数,则递增和递减会花费更多时间来刷新缓存,并且因为它不允许重新排序。请记住,每次复制这样的指针时,都必须增加引用计数器。每次销毁一个实例时,您都必须再次递减计数器。与不时使用标记和清除 GC 对引用进行计数相比,维护引用计数会累积更高的开销。
  • 最后,引用计数的指针需要程序员积极考虑循环的可能性。GC 可以自动检测和中断循环。

如果您牢记上述内容,GC 是一种替代方案。它确实有一些缺点,比如不确定性清理,但是 Java 和 C# 表明你可以忍受这个,没有什么可以阻止你在真正需要它的地方自己编程。

于 2013-05-06T06:04:44.263 回答
1

通常,您可以使用 RAII 和智能指针(例如C++11中的shared_ptr和)来解决问题。unique_ptr

但是,如果您需要垃圾收集,请查看 Boehm 的垃圾收集器。operator new您可以按以下方式重载。

enum GCPlacement {
    NoGC,
    GC,
};

void* operator new(size_t size, GCPlacement gcp) {
    void* toReturn;

    if (gcp == GC) toReturn = GC_MALLOC(size);
    else toReturn = GC_MALLOC_UNCOLLECTABLE(size);

    if (!toReturn) throw std::bad_alloc();
    else return toReturn;
}

void operator delete(void* p, GCPlacement) {
    GC_FREE(p);
}

现在,您可以按如下方式分配垃圾回收内存:

Object* o = new (GC) Object();

如果需要,您还可以从gcboehmgc 提供的类派生某些类,以指示应始终使用垃圾回收来分配这些类。

C++/CLI 是另一种解决方案,但请注意,它在技术上不是 C++(它是 C++ 部分实现的扩展),它会将您与 Microsoft/.NET 平台联系起来——本质上,它只是具有 C++ 语法的 C# .

于 2013-05-06T06:34:20.087 回答