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
二、sp类
sp类在源代码中既是轻量级指针的实现类,也是强指针的实现类。这里只关注轻量级指针相关的代码:
代码目录:framework/base/include/utils/StrongPointer.h
再来看看两个构造函数的具体实现:
析构函数的实现:
二、简单应用
定义一个普通的Person类:
在这个普通的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代码如下:
接下来在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> ,重新编译即可运行:
可以看到,析构函数正常执行,满足我们的预期。
一、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> ,重新编译即可运行:
可以看到,析构函数正常执行,满足我们的预期。
相关文章推荐
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析(2)
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- (转)Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析 转载
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- 老罗 Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析(5)
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析(1)
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析
- Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析