智能指针来源
由于android系统底层的很大的一部分是用C++实现的,C++的开发就难免会使用到指针的这个知识 点。而C++的难点和容易出问题的也在于指针。使用指针出错,常常会引发带来对项目具有毁灭性的错误,内存泄漏、逻辑错误、系统崩溃。
引发指针错误情况表现常常有如下几个表现情况:
1.申请了内存空间,但是忘记释放指针所指向的对象占用的内存空间。
2.使用了无效的指针。
因此在android的C++代码部分采用了智能指针的技术。智能指针通过一种能够自动危害对象引用计数的技术。来解决C++中指针存在的缺陷问题。
在android系统中提供了三种类型的C++智能指针,分别为:轻量级智能指针、强指针、弱指针。
下面主要通过进行分析轻量级指针的实现原理。
轻量级指针
轻量级指针就是通过利用简单的引用计数计数类维护对象的生命周期,如果一个类的对象支持使用轻量级指针,那么它就必须要从LightRefBase类进行继承,因为这个LightRefBase类提供了一个简单的引用计数器。
LightRefBase类定义
下面的源码主要依据android5.0的源码进行分析的。LightRefBase类的定义在android系统中的\frameworks\rs\cpp\util\RefBase.h 这个文件中。
LightRefBase类也是一个模板类。模板参数T表示对象的实际类型,它必须进行对LightRefBase这个类继承。
//模板类
template <class T>
class LightRefBase
{
public:
//公共的内联函数
inline LightRefBase() : mCount(0) { }
inline void incStrong(__attribute__((unused)) const void* id) const {
__sync_fetch_and_add(&mCount, 1);
}
inline void decStrong(__attribute__((unused)) const void* id) const {
if (__sync_fetch_and_sub(&mCount, 1) == 1) {
delete static_cast<const T*>(this);
}
}
//! DEBUGGING ONLY: Get current strong ref count.
inline int32_t getStrongCount() const {
return mCount;
}
typedef LightRefBase<T> basetype;
protected:
//内联的虚构函数
inline ~LightRefBase() { }
private:
friend class ReferenceMover;
inline static void moveReferences(void*, void const*, size_t,
const ReferenceConverterBase&) { }
private:
mutable volatile int32_t mCount;
};
上面LightRefBase类定义涉及到几个知识点:
1、C++的三个访问权限类型:public、protected、private。
public:可以被任意实体访问。
protected:只允许子类及本类的成员函数访问。
private:只允许本类的成员函数访问。
2、C++中的inline内联函数
在函数第一部分如果包含有inline关键字的函数,那么这个函数就表示为内联函数。内联函数主要为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题。
inline的使用是有所限制的,inline只适合涵数体内代码简单的涵数使用,不能包含复杂的结构控制语句例如while、switch,并且不能内联函数本身不能是直接递归函数(递归函数:自己内部还调用自己的函数)。
3、C++中的friend友元函数
C++中的友元机制允许类的非公有成员被一个类或者函数访问,友元按类型分为三种:普通非类成员函数作为友元,类的成员函数作为友元,类作为友元。
友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend。
4、C++中的mutable关键字
mutable是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
5、C++中的template类模板
一个类模板(也称为类属类或类生成类)同意用户为类定义一种模式。使得类中的某些数据成员、默写成员函数的參数、某些成员函数的返回值,能够取随意类型(包含系统提前定义的和用户自己定义的)。
类模板的应用场景:多个类有着共同操作,但是数据类型不同。
LightRefBase的实现类
轻量级LightRefBase类的实现类为wp类,它也是在\frameworks\rs\cpp\util\RefBase.h 这个文件中。wp也是一个模板类,模板参数T表示的是对象的实际类型,它必须继承LightRefBase类。由于wp类也是强指针的实现类,因此我们只需要分析下该wp类中关于轻量级指针类的实现部分就可以了。
//模板类
template <typename T>
class wp
{
public:
typedef typename RefBase::weakref_type weakref_type;
//轻量级指针需要用到的构造函数
inline wp() : m_ptr(0) { }
wp(T* other);
wp(const wp<T>& other);
wp(const sp<T>& other);
template<typename U> wp(U* other);
template<typename U> wp(const sp<U>& other);
template<typename U> wp(const wp<U>& other);
//轻量级指针需要用到的虚构函数
~wp();
// Assignment
wp& operator = (T* other);
wp& operator = (const wp<T>& other);
wp& operator = (const sp<T>& other);
template<typename U> wp& operator = (U* other);
template<typename U> wp& operator = (const wp<U>& other);
template<typename U> wp& operator = (const sp<U>& other);
void set_object_and_refs(T* other, weakref_type* refs);
// promotion to sp
sp<T> promote() const;
// Reset
void clear();
// Accessors
inline weakref_type* get_refs() const { return m_refs; }
inline T* unsafe_get() const { return m_ptr; }
// Operators
COMPARE_WEAK(==)
COMPARE_WEAK(!=)
COMPARE_WEAK(>)
COMPARE_WEAK(<)
COMPARE_WEAK(<=)
COMPARE_WEAK(>=)
inline bool operator == (const wp<T>& o) const {
return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
}
template<typename U>
inline bool operator == (const wp<U>& o) const {
return m_ptr == o.m_ptr;
}
inline bool operator > (const wp<T>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
}
template<typename U>
inline bool operator > (const wp<U>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
}
inline bool operator < (const wp<T>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
}
template<typename U>
inline bool operator < (const wp<U>& o) const {
return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
}
inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
private:
template<typename Y> friend class sp;
template<typename Y> friend class wp;
//轻量级指针会用到的变量m_ptr
T* m_ptr;
weakref_type* m_refs;
};
总结
通过前面的概念和系统源码实现功能原理分析,我们如果要使用轻量级指针的话,那么要包含头文件并采用继承LightRefBase类的方式,那么就可以使用轻量级指针的功能了。