概述:函数
Android中定义了两种智能指针类型,一种是强指针sp(strong pointer),另一种是弱指针(weak pointer)。其实称之为强引用和弱引用更合适一些。强指针与通常意义的智能指针概念相同,经过引用计数来记录有多少使用者在使用一个对象,若是全部使用者都放弃了对该对象的引用,则该对象将被自动销毁。
弱指针也指向一个对象,可是弱指针仅仅记录该对象的地址,不能经过弱指针来访问该对象,也就是说不能经过弱智真来调用对象的成员函数或访问对象的成员变量。要想访问弱指针所指向的对象,需首先经过wp类所提供的promote()方法将弱指针升级为强指针。弱指针所指向的对象是有可能在其它地方被销毁的,若是对象已经被销毁,wp的promote()方法将返回空指针,这样就能避免出现地址访问错的状况。this
这些都经过source code来解释。指针
本文总结基于Android 7.0rest
source code:system/core/include/utils/StrongPointer.h(其余的版本路径应该都在framwork目录下)code
template<typename T>
class sp {
public:
inline sp() : m_ptr(0) { }
sp(T* other);
sp(const sp<T>& other);
sp(sp<T>&& other);
template<typename U> sp(U* other);
template<typename U> sp(const sp<U>& other);
template<typename U> sp(sp<U>&& other);
~sp();
// Assignment
sp& operator = (T* other);
sp& operator = (const sp<T>& other);
sp& operator = (sp<T>&& other);
template<typename U> sp& operator = (const sp<U>& other);
template<typename U> sp& operator = (sp<U>&& other);
template<typename U> sp& operator = (U* other);
//! Special optimization for use by ProcessState (and nobody else).
void force_set(T* other);
// Reset
void clear();
// Accessors
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
// Operators
COMPARE(==)
COMPARE(!=)
COMPARE(>)
COMPARE(<)
COMPARE(<=)
COMPARE(>=)
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
void set_pointer(T* ptr);
T* m_ptr;
};
首先看下sp的定义,分几部分:对象
一、这是个模板类ci
对于模板,详细看 C++模板详解get
二、类型T、U是指针变量的类型io
三、有7个构造函数、6个“=”的重载模板
四、宏COMPARE的6个函数都是运算符的重载
五、m_ptr就是指针变量,后面的全部操做都是经过这个来
来看下sp构造函数的实现:
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) {
if (other) //若是构造函数形参的指针不为null,该指针的计数加1,这个后面解释
other->incStrong(this);
}
template<typename T>
sp<T>::sp(const sp<T>& other)//实参为sp<T>类型的对象,这里形参为引用
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template<typename T>
sp<T>::sp(sp<T>&& other) //这里C++11中的移动构造函数,会在另外一篇博文中详解
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
template<typename T> template<typename U>
sp<T>::sp(U* other) //这里大部分是子类往父类转换
: m_ptr(other) {
if (other)
((T*) other)->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
: m_ptr(other.m_ptr) {
if (m_ptr)
m_ptr->incStrong(this);
}
template<typename T> template<typename U>
sp<T>::sp(sp<U>&& other)//一样是C++11特性移动构造函数,后面详解
: m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
sp构造就是为了给指针T或者指针U多一个引用的地方,因此,在构造的时候必须作两件事情:
一、初始化sp中关键的指针m_ptr,也就是实参的指针
二、m_ptr也就是实参指针必需要调用incStrong()进行计数加1
构造的时候原来sp的引用为0,无需对m_ptr进行decStrong(),但下面的运算符重载就不是这样了。
对于incStrong 和 decStrong暂时理解为指针m_ptr的计数加1和减1,后面会详解。
再来看下sp中的赋值运算符重载:
template<typename T>
sp<T>& sp<T>::operator =(const sp<T>& other) {
T* otherPtr(other.m_ptr);
if (otherPtr)
otherPtr->incStrong(this);//参数other中的指针m_ptr要多一个引用了,调用incStrong()
if (m_ptr)
m_ptr->decStrong(this);//当前的指针须要被other代替,那么目前的指针m_ptr的引用计数须要减1
m_ptr = otherPtr;
return *this;
}
template<typename T>
sp<T>& sp<T>::operator =(sp<T>&& other) {
if (m_ptr)
m_ptr->decStrong(this);//这里是移动赋值,会将other中的m_ptr直接移动给这里的m_ptr,以前要先decStrong
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
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;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(const sp<U>& other) {//考虑到子类向父类赋值
T* otherPtr(other.m_ptr);
if (otherPtr)
otherPtr->incStrong(this);
if (m_ptr)
m_ptr->decStrong(this);
m_ptr = otherPtr;
return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator =(sp<U>&& other) {
if (m_ptr)
m_ptr->decStrong(this);
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
return *this;
}
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;
}
6个赋值函数,或者叫6个 “=” 的重载中注意的是原来的decStrong 和新的指针的incStrong。
再来看下sp的析构函数:
template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this);
}
当sp不在使用的时候,指针T *m_ptr须要将计数减1。
再来看下三个获取指针的方式:
inline T& operator* () const { return *m_ptr; }
inline T* operator-> () const { return m_ptr; }
inline T* get() const { return m_ptr; }
例如:
class Test {
public:
Test() {}
~Test() {}
void test() { cout << "just for test ...\n";}
};
main () {
sp<Test> hehe(new Test()); //构造的时候能够直接传入指针
hehe->test(); //经过 -> 指向指针m_ptr,直接调用Test的test函数
*hehe.test(); //经过 * 找到对应的Test 引用
Test *t = hehe.get(); //sp 中get函数就是为了获取指针m_ptr
t->test();
}
再来看下其余的函数:
template<typename T> void sp<T>::force_set(T* other) {//特殊须要用,通常不会用到 other->forceIncStrong(this); m_ptr = other; } template<typename T> void sp<T>::clear() {//作sp rest功能使用,会将指针的计数减1,指针置为空指针,注意C++11上用nullptr if (m_ptr) { m_ptr->decStrong(this); m_ptr = 0; } } template<typename T> void sp<T>::set_pointer(T* ptr) {//这个是private函数,wp在作promote的时候会使用到,wp经过friend方式调用到这里。 m_ptr = ptr; }