前言
Linus Benedict Torvalds : RTFSC – Read The Funning Source Code
设计理念
为了避免像C++指针里的常见问题而重新设计更“安全”的指针。C++中常见的问题:1、指针没初始化;2、new了后忘记delete;3、野指针。
指针类型
Android中定义了两种智能指针类型,一种是强指针sp(strong pointer),另外一种是弱指针(weak pointer)。
强指针sp(strong pointer):
与一般意义的智能指针概念相同,通过引用计数来记录有多少使用者在使用一个对象,如果所有使用者都放弃了对该对象的引用,则该对象将被自动销毁。
弱指针(weak pointer):
弱指针也指向一个对象,但是弱指针仅仅记录该对象的地址,不能通过弱指针来访问该对象,也就是说不能通过弱指针来调用对象的成员函数或访问对象的成员变量。
指针类实现
如果要使用智能指针来引用这个类的对象,那么这个类需满足下列两个前提条件:
1:这个类是基类RefBase的子类或间接子类;
2:这个类必须定义虚构造函数,即它的构造函数需要这样定义:virtual ~MyClass();
轻量级引用计数类LightRefBase
|
|
android_atomic_inc()^footnote
android_atomic_dec()^footnote2
计数器,递减到0的时候就delete掉对象。
重量级引用计数类 RefBase
不同于LightRefBase的是,RefBase内部并没有使用一个变量来维护引用计数,而是通过一个weakref_impl *类型的成员来维护引用计数,并且同时提供了强引用计数和弱引用计数。weakref_impl继承于RefBase::weakref_type。
|
|
RefBase类的成员变量mRefs的类型为weakref_impl指针,在去除debug代码后:
类图:
强指针数类 sp
|
|
使用轻量级引用计数:
重点只关注成员变量m_ptr、构造函数和析构函数;
继承轻量级引用计数使用例子:
使用重量级引用计数:
强指针:
使用重量级引用计数一定是继承于RefBase类,在构造函数传进来的就是RefBase类,调用的是RefBase类的incStrong函数。
在RefBase类的incStrong函数中,主要做了三件事情:一是增加弱引用计数;二是增加强引用计数;三是如果发现是首次调用这个对象的incStrong函数,就会调用一个这个对象的onFirstRef函数,让对象有机会在对象被首次引用时做一些处理逻辑。
总体来说强指针类sp在其构造函数里面所做的事情就是分别为目标对象的强引用计数和弱引和计数增加了1。
在析构函数里,如果发现减1前,此对象的强引用计数为1,就说明从此以后,就再没有地方引用这个目标对象了,这时候,就要看看是否要delete这个目标对象了,在强引用计数为0的情况下,如果对象的标志位OBJECT_LIFETIME_WEAK被设置了,就说明这个对象的生命周期是受弱引用计数所控制的,因此,这时候就不能delete对象,要等到弱引用计数也为0的情况下,才能delete这个对象。
总结:
A:如果对象的标志位被设置为0,那么只要发现对象的强引用计数值为0,那就会自动delete掉这个对象;
B:如果对象的标志位被设置为OBJECT_LIFETIME_WEAK,那么只有当对象的强引用计数和弱引用计数都为0的时候,才会自动delete掉这个对象;
C:如果对象的标志位被设置为OBJECT_LIFETIME_FOREVER,那么对象就永远不会自动被delete掉,谁new出来的对象谁来delete掉。
弱指针数类 wp
弱指针所使用的引用计数类与强指针一样,都是RefBase类。
弱指针的最大特点是它不能直接操作目标对象,因为弱指针类没有重载*和->操作符号,而强指针重载了这两个操作符号。如果我们要操作目标对象,就要把弱指针升级为强指针。
强弱指针用法
|
|