什么是强指针和弱指针?

36
我对“强指针”和“弱指针”的概念感到困惑。Diane Hackborn本人曾说过:“只要有强指针,对象就会一直存在;当最后一个强指针被释放时,对象就被销毁了。弱指针只能进行比较并尝试升级为强指针;如果对象上没有其他强指针,则后者将失败。”这对我来说相当不清楚。强指针是否等同于(boost::)shared pointer?如果弱指针只是为了尝试将自己提升为强指针,那它的作用是什么呢?也就是说,我们何时需要使用弱指针和强指针?
更新:感谢大家的回答,但我特别询问的是安卓内核中的spwp,它们与Java的引用完全无关。
基本上我正在尝试破解这里的代码http://www.androidenea.com/2010/03/share-memory-using-ashmem-and-binder-in.html,但不太理解spwp的用法。 更新: 实际答案在接受答案的评论中。感谢Gabe Sechan:
强指针和弱指针是不同的智能指针实现,基本上做的事情相同-当指针超出范围时,只要至少有一个强指针引用它,它就不会被释放。如果只有弱指针(或没有任何内容)引用,则会被释放。检查是在强引用或弱引用解除作用域时进行的。
如果我有10个弱指针引用同一个对象,并且其中一个10个超出范围,对象将被销毁?而对于强指针,只有当所有10个都超出范围时,对象才会被销毁?
是的,几乎是这样。如果您只有10个弱指针,那么当最后一个强指针超出范围时,它很可能已经超出了范围。如果存在多余的内存,实现可能允许其继续存在一段时间,但如果进入低内存条件并且她的引用中没有高级实现,它将被删除。而使用这种方法仍然主要是缓存-它大致等同于boost shared_ptr和boost weak_ptr。因此,基本上,弱指针所引用的对象随时可能消失。

+1 是为了表扬解释这个概念的努力。 - miller
3个回答

41

在Android中,sp代表StrongPointer,指向的对象占用的内存将在引用计数等于0时被释放。wp代表WeakPointer,因此如果我有一个弱指针,我不关心所引用的对象是否存活。它可能用于一些缓存和比较场景。

首先,快速查看StrongPointer.h中的sp实现。

它只是一个引用计数的包装器。例如,

template<typename T> template<typename U>
sp<T>& sp<T>::operator = (U* other)
{
    if (other) ((T*)other)->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = other;
    return *this;
}

如果您使用sp<IBinder> strongPointer创建了一个强指针,那么m_ptr就是被引用的对象。正如您在源代码中看到的,sp模板只表示一个强指针,因此只要我持有这个sp,系统就不会释放内存。它不维护引用计数器。计数器由RefBase类维护。为了使用StrongPointer,您的obj需要是RefBase的实例。
RefBase类维护强引用计数器和弱引用计数器,唯一的区别是当强计数为0时,被引用的对象将被释放。此外,对于由Refbase管理的对象,可以同时由一些强指针和弱指针引用。
您可以在Android框架中广泛使用StrongPointers,其中大部分都是在IBinder对象上,本地binder对象可以通过不同的进程传递。不同的进程可以持有对同一对象的强指针,只要一个进程仍然持有指针,该对象就不会被系统撤销。

为什么类 sp 不像 std::shared_pointer 一样维护引用计数呢?这样分离职责的好处是什么? - Bob
@Adrian 对于 std::shared_ptr,它实际上是一个内部类,用于保存引用计数;shared_ptr 持有指向该内部类的指针并复制该指针。(在大多数情况下) - Paul Stelian

15

Android旨在使用Java进行编程,而不是C。任何来自Android团队的文档都会提及该语言。在Java中有强引用和弱引用。弱引用不会阻止垃圾回收器清理它,而强引用会。它们用于一些操作系统上的缓存,但在Android 3.0之后,仅持有对象的弱引用意味着它将被立即收集。

C没有弱引用的等效物,因为它没有垃圾回收机制。


6
实际上我正在编写安卓的内核,所以不需要Java,但还是谢谢。 - Max
5
那么你应该对弱引用或强引用不感兴趣 :-) - fedepaol
7
好的,你应该告诉我们,在提出Android问题的人中,少于0.1%的人正在使用AOSP,他们指的是用户级别的Android。因此,强引用和弱引用是不同的智能指针实现,它们做的事情大致相同——当一个指针超出作用域时,只要至少有一个强引用指向它,它就不会被释放。如果只有弱引用(或没有引用),它将被释放。这个检查是在强引用或弱引用取消引用时进行的。 - Gabe Sechan
4
@crazyfffan,我认为我们都误解了你的问题。强引用和弱引用只与Java有关。它与内核没有任何关系。您可以在内核上运行ACME Corps Best Ever Mobile Operating System,该系统使用Pasvasicoboltran编程,这不会有任何影响。内核对用户空间一无所知。 - Simon
7
几乎是的。如果你只有10个弱指针,当最后一个强指针超出其作用域时,它很可能已经失效了。如果有多余的内存,实现可能允许它停留更长时间,但如果进入低内存状态,则会被删除,而且从她的引用中看来,它们的实现并不那么高级。而且这个东西主要还是用于缓存——它大致相当于boost shared_ptr和boost weak_ptr。所以基本上,一个弱指针可能随时引用的对象消失。 - Gabe Sechan
显示剩余5条评论

2

1
Oraclified链接:https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references - Isabaellchen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接