【问题标题】:Soft (not: weak) references in C++ - Is it possible? Is there an implementation?C ++中的软(不是:弱)引用-可能吗?有实现吗?
【发布时间】:2011-03-11 15:22:44
【问题描述】:

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

在 Java 中,内存由垃圾收集器管理,垃圾收集器将内置对象引用视为 strongWeakReference 视为 weakSoftReference 视为某事介于两者之间(可能由 GC 收集,但也可能在 GC 中幸存下来),这对于缓存一段时间的对象非常方便,但一旦可用内存变少就将其丢弃。

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

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

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

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

【问题讨论】:

  • 在家中的软参考到底是什么?
  • 我也不明白——它一定是某种参考。
  • “当它在家里”是一个短语,意思是......呃......真的不多。 “当它在家里时,到底什么是软参考?”意思是“什么(到底)是软参考?”
  • @JUST:如果你是在回复我的评论,那是个玩笑,虽然很弱。
  • @Amnon:是软的,不是软的。

标签: c++ memory-management boost shared-ptr soft-references


【解决方案1】:

正如其他人指出的那样,您可以在 Boost 库中找到 referenced counted pointers(以及他们的服务员 weak counterparts),但是 软参考 想法中缺少的是对运行时环境内存的一些认识约束。例如,在 Java 中,SoftReference 的功能与WeakReference 没有本质区别。而是the contract for how the runtime will preserve or evict the two kinds of references 面对不同的内存压力。

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

【讨论】:

  • 让我问...这不是垃圾收集器所做的吗?在程序需要时回收内存?
  • 是的,垃圾收集器可以使以前分配给不再可访问对象的内存可用于新对象,无论是急切地还是仅在需要时。问题不在于如何集成垃圾收集器,而在于是否可以模拟收集器的压力意识。在 C++ 中使用强指针和弱指针提供了一种垃圾收集,但没有办法表达“仅在我们需要更多内存之前固定对象”的愿望。强指针无条件固定,弱指针根本不固定。软指针存在于这两个极端之间。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    但比起复制 Java 行为,我更愿意选择更原生于 C++ 的解决方案——但没有什么能阻止你这样做。

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

        • 我不确定我是否明白,正如 Brian 所描述的那样,软引用是内存泄漏,而 LRU 缓存却不是。要么你需要这个对象,要么你不需要。
        • 根据您的编辑,我也编辑了我的答案。我忘了提到可能的对象创建起来相当昂贵。最近最少使用的策略实际上是一个好主意。无论如何,我问自己是否需要手动将其放入缓存管理对象的实现中,或者是否有类似的功能可以放入弱引用之类的东西中。
        • @Dennis:LRU 具有固定大小。它可以清洗。它由拥有对象控制。软引用不受控制。如果你实现了一个 LRU,那么你就可以控制那个内存。如果您使用软引用,任何人都可以使用软引用。 LRU 缓存是明确定义和拥有的。软引用是每个人的一大堆。
        • "所有人的聚集地" = 如果有空间,这个对象就值得拥有,如果没有,就不值得拥有。 “LRU 缓存” = 我将使用 1GB 的内存,我不在乎这是否意味着您的其他应用程序将无法运行。在桌面操作系统上,内存不足是一个罕见的问题,并且不需要太多的应用程序技术。 “如果有空间”基本上总是正确的。在受限系统上,应用程序在内存使用方面进行协作非常重要,而软引用是这样做的一种(相对生硬的)工具。
        • 这太疯狂了。使用固定大小的缓存不如使用根据外部资源因素(例如可用内存)进行扩展的动态缓存高效。
        猜你喜欢
        • 2011-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-07
        • 1970-01-01
        • 2020-05-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多