为了管理堆上的对象的生命周期,Android引入了引用计数和强弱指针。
假设有以下的场景:
{
class A{
};
A *p = new A();
//delete p;
}
如果我们忘记使用delete p 释放刚刚new出来的对象,就会发生内存泄漏。即使不会忘记释放,也会有一个问题:在什么时候去调用delete p?p可能在很多地方都在使用,如果一个地方使用完了就调用delete p,显然会对其他代码产生影响。这就提出了一个需求:
(1)当p还在被使用就不能释放,当程序中没有地方使用p的时候就要释放掉这块内存。
如果仅仅是实现了这点还是不够的,因为如此一来,何时销毁P将会有限制(要考虑P是否还在被其他对象在使用),因此我们还希望有这样的一个功能,
(2)只有一个对象管理p的释放,其他的地方都是保存着p的一个“引用”,每次想使用p的时候都必须探测一下p是否还存在,如果存在就可以使用。
为了实现以上目的,android设计了四个类:LightRefBase,RefBase,sp,wp。
LightRefBase实现了上文中的需求(1),为轻量级的引用基类,只支持强指针sp,RefBase实现了(1)和(2),同时支持sp和wp。
首先我们看下LightRefBase和sp的类图,图中TestObject是用户定义的测试类,继承了LightRefBase。
LightRefBase是一个模版类,保存着一个int型的引用计数,表示有多少个地方在使用T。函数incStrong用于增加引用计数,函数decStrong用于减少引用计数(在此函数中会检查引用计数,当引用计数为0的时候就会调用delete,释放TestObject)。sp也是一个模板类,其中有一个模板指针T,指向实际的对象。在本例中就是指向TestObject对象。
sp<TestObject> test = new TestObject();
sp重载了操作符” = ”,在重载符中做了两件事情:
1.增加other的引用计数;
2.如果m_ptr不为空,就减少其引用计数,然后将other保存在m_ptr中。
- template<typename T>
- sp<T>& sp<T>::operator = (T* other)
- {
- if (other) other->incStrong(this);
- if (m_ptr) m_ptr->decStrong(this);
- m_ptr = other;
- return *this;
- }
当过了sp的作用域,sp就会被析构:
当过了sp的作用域,sp就会被析构,在析构函数中会调用m_ptr的函数decStrong减少计数。
- template<typename T>
- sp<T>::~sp()
- {
- if (m_ptr) m_ptr->decStrong(this);
- }
每次减少m_ptr的引用计数的时候,最终都会调用LightRefBase的decStrong,检查引用计数是否为0,如果是,就会删除我们new 出来的TestObject。
轻量级的引用和sp指针结合就实现了对堆上分配对象的生命周期的自动管理。只要这个对象还有地方在使用就不会释放,一旦引用计数为0,没人使用了,就会被delete。