为什么弱指针有用吗?(Why are weak pointers useful?)

2019-08-16 22:50发布

我一直在垃圾收集阅读了寻找功能,在我的编程语言,包括和我遇到“弱指针”来了。 从这里 :

弱指针的指针一样,只是从弱指针引用并不阻止垃圾回收和弱指针必须在使用之前检查其有效性。

弱指针与垃圾回收器交互,因为它们所涉及的存储实际上可能仍然是有效的,但含有不同的对象比创建它的弱指针时一样。 因此,每当一个垃圾收集器回收内存,它必须检查,看看是否有任何微弱的指针指向它,并将其标记为无效(这不需要在这么幼稚的方式来实现)。

我从来没有听说过弱指针之前。 我想支持我的语言的许多功能,但在这种情况下,我不能为我的生活觉得这个地方将是有益的情况。 对于什么将一个使用弱指针?

Answer 1:

一个典型的使用情况是附加对象属性存储。 假设你有一组固定成员的一类,而且,从外面看,你要添加更多的成员。 所以你创建一个字典对象 - >属性,其中键是弱引用。 然后,字典不阻止垃圾回收的关键; 删除该对象也应该触发在WeakKeyDictionary(例如,通过一个回调的装置)除去的值。



Answer 2:

A really big one is caching. Let's think through how a cache would work:

The idea behind a cache is to store objects in memory until memory pressure becomes so great that some of the objects need to be pushed out (or are explicitly invalidated of course). So your cache repository object must hold on to these objects somehow. By holding onto them via weak reference, when the garbage collector goes looking for things to consume because memory is low, the items referred to only by weak reference will appear as candidates for garbage collection. Items in the cache that are currently being used by other code will have hard references still active, so those items will be protected from garbage collection.

In most situations you won't be rolling your own caching mechanism, but it is common to use a cache. Let's suppose you want to have a property which refers to an object in cache, and that property stays in scope for a long time. You would prefer to fetch the object from cache, but if it's not available, you can get it from persisted storage. You also don't want to force that particular object to stay in memory if pressure gets too high. So you can use a weak reference to that object, which will allow you to fetch it if it is available but also allow it to fall out of cache.



Answer 3:

如果你的语言的垃圾回收器是不能收集圆形数据结构的,那么你可以使用弱引用,以使其能够做到这一点。 通常情况下,如果你有这不得不互相引用两个对象,但没有其他外部对象有这两个参考,他们将垃圾收集的候选人。 但是,一个天真的垃圾收集器不会收集它们,因为它们含有相互之间的引用。

为了解决这个问题,你做起来很一个对象具有很强的参考到第二,但第二个具有弱参照第一。 然后,当最后一个外参考第一对象消失,第一个对象就成为垃圾收集的候选人,由第二跟随其后不久,因为现在它的唯一参考较弱。



Answer 4:

另一个例子......不太缓存,但类似的:假设一个I / O库提供了包装文件描述符,并允许访问文件的对象。 当收集的对象,文件描述符被关闭。 人们希望能够列出当前打开的所有文件。 如果你用强的指针清单,然后文件永远不会关闭。



Answer 5:

当你想保留对象的缓存列表,但不能阻止这些对象从获取该对象的“真实”的主人是用它做垃圾回收使用它们。

Web浏览器可能有保留引用,浏览器加载其他地方并保存在历史记录/磁盘缓存图像对象的历史记录对象。 Web浏览器可能会届满的图像中的一个(用户清除缓存,经过高速缓存超时等),但该网页将仍然有参考/指针。 如果页面使用弱引用/指针如预期的对象将消失,记忆会被垃圾收集。



Answer 6:

对于具有弱引用的一个重要原因是对付一个对象可以作为管道的信息或事件源连接到一个或多个监听器的可能性。 如果没有任何听众,没有理由继续将信息发送到管道。

举个例子,可枚举集合,它允许在枚举期间更新。 收集可能需要通知任何活动的统计员,它已被改变,因此这些普查员可以相应地调整自己。 如果有些普查员得到由它们的创造者抛弃,但收集持有他们强引用,这些普查员将继续存在(和工艺更新通知)只要集合存在。 如果集合本身将为应用程序的生命存在,这些普查员将有效地成为永久的内存泄漏。

如果集合持有的统计员弱引用,这个问题就可以很大程度上解决。 如果枚举被放弃,这将是符合垃圾收集,即使收集仍持有弱引用。 下一次集合更改,也可以通过看其弱引用的列表中,将更新发送到那些仍然有效的,并从其列表中删除不属于的。

这将有可能使用终结一些额外的对象一起实现诸多的弱引用的影响,并有可能做出这样的实现比使用弱引用那些更有效率,但也有很多陷阱,它是很难避免的错误。 这是很容易做的WeakReference使用一个正确的做法。 该方法可能不是最佳的效率,但它不会失败得很惨。



Answer 7:

弱指针保持什么成为“生命支持”对象的指针指向一个形式持有它们。

假设你有一个Viewport类和2个UI类,和Widget类的布赫。 您希望您的用户界面来控制它创建的窗口小部件的使用寿命,让你的UI保持SharedPtrs所有它所控制的小工具。 只要你的UI对象是活的,没有小工具的这refrences会被垃圾收集(感谢SharedPtr)。

然而,视口是你的类,它实际的图纸,让你的UI需要一个指针传递视口的小工具,以便它可以吸引他们。 无论出于何种原因,您希望您的积极UI类更改为另一种。 让我们考虑两种情况,一是在UI通过视窗WeakPtrs和一个地方传递SharedPtrs(指着小工具)。

如果你已通过视窗所有控件的WeakPointers,只要UI类被删除就不会有更多的SharedPointers的小工具,这样他们就被垃圾收集,视口的对象引用不会让他们的“生命支持”,而这正是你想要的,因为你甚至不使用UI了,更别说小工具它创造。

现在,考虑你已通过视口中的SharedPointer,您删除UI,和Widgets是不是垃圾收集! 为什么? 因为视口,这仍然是活着具有阵列(向量或列表,等等)充分SharedPtrs到小部件。 视口实际上已成为“生命支持”他们的一个形式,即使你已经删除这是在控制了其他UI对象部件的UI。

一般而言,语言/系统/框架将垃圾收集什么东西,除非有一个“强”引用它的地方在内存中。 试想一下,如果一切都产生了强烈的参考一切,没有什么会永远得到垃圾回收! 有时候你想要的行为,有时候你不知道。 如果您使用WeakPtr,并且没有共享/ StrongPtrs留在物体(只有WeakPtrs),那么对象将是尽管WeakPtr引用垃圾收集和WeakPtrs(应该)设置为NULL(或删除,或指点东西)。

同样,当您使用WeakPtr你基本上是让你给它太多的目的是能够访问数据,但WeakPtr不会阻止该对象的垃圾收集它指向像SharedPtr会。 当你想到SharedPtr,认为“生命支持”,WeakPtr,NO“生命支持。” 不会(一般)发生垃圾收集,直到对象具有零生命支持。



Answer 8:

弱引用可在例如缓存场景中使用 - 你可以通过弱引用访问数据,但如果你不访问数据很长一段时间或有高内存压力时,GC可以释放它。



Answer 9:

原因在所有垃圾收集是在像C语言,其中的内存管理是完全编程的明确控制下,当对象所有权,传来传去,特别是螺纹或更难之间,进程共享内存之间,避免了内存泄漏和悬摆指针会变得非常困难。 如果这还不够硬,还必须处理需要获得更多的对象太多,无法存放在内存中时,你需要有一个办法可以免费了一段时间的一些对象,以便其他对象可以在存储器中。

所以,有些语言(例如,Perl和Lisp语言,Java的)提供了一种机制在那里你可以停止“使用”的对象和垃圾回收器最终会发现这一点,并用于对象释放内存。 它正确地做到这一点无需程序员担心,他们可以得到的所有方法是错误的(尽管有很多方式程序员可以搞砸)。

如果您在概念上乘的次数,你通过它需要计算对象的价值,并可能通过不因为保持一个现成的或由物体的大小的物体的成本再乘以时间访问对象大对象在内存中,可以防止保持周围的几个更小的物体,你可以对象分为三类。

有些对象是很重要的,你要明确地管理它们的存在,它们不会被垃圾收集器管理或者他们必须永远不会被收集,直到明确释放。 有些对象是廉价的计算,是小的,不经常访问的或有类似的特点,使他们能够在任何时间收集垃圾。

第三类,这是昂贵的重新计算,但可以重新计算,对象是有些经常访问的(也许是时间的短脉冲),大尺寸的等是第三类。 您想保留在内存中尽可能长的时间,因为他们可能会被再次使用,但你不想跑出来的用于关键对象的内存。 这些是弱引用候选人。

你想这些对象尽可能长地保持周围,如果他们不与关键资源发生冲突,但如果需要的重要资源存储,因为它可以在需要时重新计算一次,他们应该被丢弃。 这些帽子弱指针的。

这方面的一个例子可能是照片。 假设你有一个照片网页,数以千计的图片中显示的。 你需要知道有多少照片进行布局,也许你需要做一个数据库查询以获取列表。 持有几千项列表存储可能是非常小的。 你想要做一次查询,并保持它的周围。

您只能在物理或许显示出几十个图片的时间,但是,在一个网页的窗格。 你并不需要为用户不能看图片取位。 当用户滚动页面,你会收集可见光图像时的实际位。 这些图片可能需要许多兆向他们展示。 如果用户滚动来回几滚动位置之间,你想不必须一遍又一遍的重取的兆字节。 但你不能把所有的图片在内存中所有的时间。 所以,你使用弱指针。

如果用户只是在几张照片看起来一遍又一遍,他们可能会留在缓存中,你不必重新提取它们。 但是,如果他们足够滚动,你需要释放一些内存,以便可见的图片可以取出。 随着弱引用,你检查你使用它之前的参考。 如果它仍然有效,你使用它。 如果它不是,你让昂贵的计算(提取)得到它。



文章来源: Why are weak pointers useful?