您的位置:首页 > 移动开发 > Android开发

Android的轻量级指针原理与使用

2017-03-09 22:14 127 查看
Android系统提供了三种类型的c++智能指针,分别为轻量级指针(Light Pointer)、强指针(Strong Pointer)、弱指针(Weak Pointer)。其中,轻量级指针使用了简单的引用计数,而强指针和弱指针分别使用了强引用计数和弱引用计数。现在分析的是Android的轻量级指针的实现与简单应用。

一、LightRefBase类

如果一个类的对象支持使用轻量级指针,那么这个类在定义时必须继承LightRefBase类。LightRefBase类提供了一个简单的引用计数器,它的定义如下:

代码目录:framework/base/include/utils/RefBase.h

template <class T>
class LightRefBase
{
public:
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
android_atomic_inc(&mCount); /*原子操作,不可被其他线程打断*/
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (android_atomic_dec(&mCount) == 1) /*原子操作,不可被其他线程打断*/ {
delete static_cast<const T*>(this); /*计数值为0,表示可以释放对象内存了*/
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount;
}

protected:
inline ~LightRefBase() { }

private:
mutable volatile int32_t mCount; /*对象的引用计数值*/
};

二、sp类

sp类在源代码中既是轻量级指针的实现类,也是强指针的实现类。这里只关注轻量级指针相关的代码:

代码目录:framework/base/include/utils/StrongPointer.h

template<typename T>
class sp {
public:
inline sp() : m_ptr(0) { } /*普通构造函数,初始化指针*/

sp(T* other); /*普通模板构造函数 ,在内部对象引用计数加一*/
sp(const sp<T>& other); /*拷贝构造函数,在内部对象引用计数加一*/
template<typename U> sp(U* other);
template<typename U> sp(const sp<U>& other);

~sp(); /*析构函数,在内部引用计数减一*/

// Assignment

sp& operator = (T* other);
sp& operator = (const sp<T>& other);

template<typename U> sp& operator = (const 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; /*成员变量:模板指针*/
};

 

再来看看两个构造函数的具体实现:

template<typename T>
sp<T>::sp(T* other)
: m_ptr(other) /*普通构造函数:初始化成员变量m_ptr*/ {
if (other)
other->incStrong(this); /*增加引用计数*/
}

template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr) /*拷贝构造函数:初始化成员变量m_ptr*/ {
if (m_ptr)
m_ptr->incStrong(this); /*增加引用计数*/
}

析构函数的实现:

template<typename T>
sp<T>::~sp() {
if (m_ptr)
m_ptr->decStrong(this); /*减少引用计数*/
}


二、简单应用

定义一个普通的Person类:

class Person {
private:
char *name ;

public:
Person() {
cout<<"Person()"<<endl ;
}

~Person() {
cout<<"~Person()"<<endl ;
}

void printInfo(void){
cout<<"just for test !"<<endl ;
}
} ;

在这个普通的Person类中,我们仅仅定义了几个普通的成员变量和普通的成员函数。这时该如何使这个类具有轻量级指针的功能呢?

1、要使这个类具有引用计数器,它在定义时必须继承LightRefBase这个模板类;

2、在使用时,先new 一个Person类,并创建一个轻量级指针来引用它;

3、接下来就可以操作Person类的成员函数了。

由于代码中用到了LightRefBase类、sp类,这两个类的定义与实现分别在RefBase.h 、StrongPointer.h ,而这两个文件在Android系统中是以库文件的形式存在的。它们位置在Android源码目录 system/core/include/utils 和 system/core/include/cutils目录下。因此,我们将这两个目录拷贝到当前应用程序目录的include目录下面。当前Person.cpp代码如下:

#include<iostream>
#include <utils/RefBase.h> /*包含RefBase.h文件,该文件中包含了StrongPointer.h,因此不必重复包含*/

using namespace std;
using namespace android; /*使用android命名空间*/

class Person : public LightRefBase<Person> /*要使这个类具有引用计数器,它在定义时必须继承LightRefBase这个模板类*/{
private:
char *name ;

public:
Person() {
cout<<"Person()"<<endl ;
}

~Person() {
cout<<"~Person()"<<endl ;
}

void printInfo(void){
cout<<"just for test !"<<endl ;
}
} ;

int main(int argc , char** argv)
{
/*使用轻量级指针*/
sp<Person> lp = new Person() ; /*普通构造*/
sp<Person> lp2 = lp ;	    /*拷贝构造*/
/*使用轻量级指针重载的运算符*/
lp->printInfo() ;
(*lp).printInfo() ;

lp2->printInfo() ;
(*lp2).printInfo() ;

return 0 ;
}

接下来在PC机上编译该Person.cpp : g++ -o Person Person.cpp -I include

发现如下错误:



在incStrong 和decStrong过程中的原子操作未定义。原因在于Android系统默认采用arm架构中的原子操作,而PC机采用x86架构,因此解决方法在RefBase.h 、StrongPointer.h 中将 #include <cutils/atomic.h> 改为 #include <cutils/atomic-x86.h> ,重新编译即可运行:



可以看到,析构函数正常执行,满足我们的预期。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐