概述
Android中的智能指针是对C++中的对象回收机制的封装,C++中的构造函数和析构函数是在对象new出来和delete的时候调用的,但是一个在销毁一个对象的时候,我们需要手动的调用delete关键字来销毁,但是在Java中我们无需在乎这些对象的销毁工作,都是由垃圾回收器来做了,所以在Android系统层,为了达到Java的这个自动管理对象的效果,就出现了智能指针的概念了,他的出现类似于Java中的回收器
内部实现也很简单,就是用两个变量来控制,一个是强引用计数变量,一个是弱引用计数变量,这两个变量都是int类型的,表示一个对象被引用多少次,两个变量会依据具体的生命管理周期模式来决定是否释放对象。
android/system/core/libutils/RefBase.cpp
android/system/core/libutils/include/utils/RefBase.h
android/system/core/libutils/include/utils/StrongPointer.h
RefBase
Android设计了基类RefBase,用以管理引用数,所有类必须从RefBase派生,RefBase是所有对象的始祖。
设计模板类sp、wp,用以引用实际对象,sp强引用和wp弱引用。sp、wp声明为栈对象,作用域结束时,自动释放,自动调用析构函数。因此,可以在sp、wp的构造函数中,增引用数;在析构函数中,减少引用计数。
专门设计weakref_impl类,该类是RefBase的内部类,用来做真正引用数管理,创建实际对象时,同时创建一个mRefs对象。不管是强引用和弱应用,都由mRefs来管理。
智能指针的实现
如果一个类想使用智能指针,那么必须满足下面两个条件:
a. 该类是虚基类RefBase的子类或间接子类
b. 该类必须定义虚构造函数。如virtual ~MyClass();
实际对象的释放,可分为强引用控制和弱引用控制。所谓强引用控制,指的是强引用数mStrong为0时,释放实际对象;弱引用控制,则指的是弱引用数mWeak为0时,才释放实际对象。
class Sheep: public RefBase { // 羊年,定义Sheep从RefBase派生
public:
Sheep(): RefBase() { }// 可显示调用RefBase的构造,也可以不用
virtual~Sheep() { }// 最好声明为virtual,以便从Sheep派生
};
void testSheep() {
Sheep*pSheep = new Sheep(); // new一个Sheep对象,这个是一个堆对象
{ // 限定sp的作用域
sp<Sheep>spSheep(pSheep); // spSheep是一个栈对象
{// 限定wp的作用域
wp<Sheep>wpSheep(pSheep);
}//调用wp的析构函数
} // 调用sp的析构函数,实际对象pSheep已释放,若再使用pSheep将会出错
}
RefBase构造和mRefs
在实例代码中,我们先定义了一个类Sheep,从RefBase派生,创建了一个实际对象,pSheep 指向实际对象。
在构造Sheep的实际对象时,将调RefBase的构造函数。RefBase的构造函数如下,在构造函数中创建mRefs。
weakref_impl从weakref_type派生,mRefs才是真正的“管家”。
RefBase::RefBase()
:mRefs(new weakref_impl(this)) // 真正管理引用计数
{}
weakref_impl(RefBase* base)
:mStrong(INITIAL_STRONG_VALUE) // 1<<28(268435456),为什么不是0?
,mWeak(0)
,mBase(base) // mBase指向实际对象
,mFlags(0) // 这个标识很重要,指定是强应用控制还是弱引用控制
{}
请注意这里的mFlags,默认值为0,可通过修改这个标志来设置是强引用控制,还是弱引用控制,代码如下:
//system/core/include/utils/RefBase.h
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
mFlags默认为0,即OBJECT_LIFETIME_STRONG,强引用控制。设置为OBJECT_LIFETIME_WEAK时,为弱引用控制。可以通过extendObjectLifetime函数修改,代码如下
//system/core/libutils/RefBase.cpp
void RefBase::extendObjectLifetime(int32_t mode)
{
android_atomic_or(mode, &mRefs->mFlags);
}