6

在 C++ 中,我使用boost::shared_ptrandboost::weak_ptr来自动删除不再需要的对象。我知道这些与引用计数有关。

在 Java 中,内存由垃圾收集器管理,它认为内置的对象引用是强介于两者之间的(可能被 GC 收集,但也可能在 GC 中幸存下来),这真的很方便用于缓存对象一段时间,但在可用内存变低时将其丢弃。WeakReferenceSoftReference

所以现在我回到了 C++,我想念软引用带来的舒适感。我想知道软引用是否完全适用于引用计数。当对一个对象的最后一个引用被清除,并且还有一个引用时,它到底什么时候会被删除呢?我可以想出一些方案,但在我看来它们都不聪明。

以防万一软引用和引用计数有适当的语义,我想知道这是否已经实现,也许以一种甚至兼容的方式boost::shared_ptr(或与此相关的 C++ TR1 等效项std::shared_ptr)。

如果这两个问题的答案都是否定的,那么在对象缓存场景中还有哪些替代方案?

编辑: 当然,我说的是缓存实际上很有用的情况,因为对象的构建成本很高(考虑对数据库的多次访问和网络查询),但有太多无法永久保存它们。

4

5 回答 5

7

正如其他人指出的那样,您可以在 Boost 库中找到引用的计数指针(及其伴随的指针),但是软引用思想中缺少的是对运行时环境的内存约束的一些认识。例如,在 Java 中, a在功能上SoftReference与 a 没有本质区别。WeakReference相反,它是关于运行时如何在面对不同的内存压力时保留或驱逐这两种引用的合同。

为了在 C++ 中模仿这种行为,您必须构建一个内存感知引用缓存,该缓存保存对应用程序其余部分将弱保存的对象的强引用。当缓存确定应用程序正在触及其内存使用上限(或任何其他限制条件)时,它将释放强引用,放弃对象以进行“收集”(达到零引用计数)并允许稍后使用弱引用检测失效。

于 2010-07-04T18:15:01.010 回答
2

如果您真的想复制这种行为,您可以使用垃圾收集器(例如: http: //www.hpl.hp.com/personal/Hans_Boehm/gc/)并使用它来处理您的对象或他们,在哪里使用 SoftReferences 会很有用。

但我更愿意寻找一种更原生于 C++ 的解决方案,而不是复制 Java 行为——但没有什么能阻止你这样做。

于 2010-07-05T00:39:46.227 回答
1

您可以实现自己的 LRU 缓存,以及与此类缓存关联的新 smart_pointer。我认为 Boost 或标准 C++ 中不存在这样的结构(无论如何我都想不到)。如果你正在做一个 web 应用程序或其他东西......你可以使用 libmemcached,它是 memcached 的 C 接口。

我发现很难想象这样一个对象的构造/销毁成本如此之高......而重新初始化很便宜......LRU缓存将变得有用。但如果你真的需要一个,你有工具来实际构建它。

于 2010-07-04T17:52:00.397 回答
0

您可以使用类似buffcacher的东西将应用程序外部的软引用数据移动到操作系统中。

我知道没有图书馆提供这个,我只推出过自己的。

它是如此快速和公平,以至于在网络服务器中缓存“安全cookie”的验证以及其他对于传统缓存来说似乎几乎很小的任务变得非常有用。

于 2011-09-27T09:52:59.440 回答
-2

不,C++ 中没有这样的东西。也不应该有。每个对象都有一个重要的用途。如果没有,为什么你还拥有它?以这种方式保留对象是内存泄漏。如果你需要一个对象,你就需要它。如果你不这样做,那就毁掉它。有用和无用之间没有中间地带,要么有目的,要么没有。

如果你绝望了,编写自己的垃圾收集器并自己实现这样的事情并非不可能。但我建议不要需要它们或根本不使用它们。

编辑:在对象缓存中,人们通常使用 LRU 缓存。当您发生缓存未命中时,对最近最少使用对象的引用将被销毁(如果缓存已满),新对象将被创建并作为最近使用的对象放入,而所有其他对象都将向下移动。但是,在实际需要 C++ 中的缓存策略之前,您通常需要从磁盘中检索项目。创建大多数对象的成本并没有那么高。

于 2010-07-04T15:01:31.717 回答