智能指针
0 引言
问题描述:
在android系统中,有很多的代码是用c++来开发的,而使用c++来编写程序,最容易因为指针使用不当而导致致命的错误,比如因为忘记释放指针所指向的对象占用内存导致内存泄露或者程序崩溃。
解决思路:
相比与c++,java的垃圾回收机制在这方便就做的比较好,系统会运行一个守护进程时刻监视各个对象的使用情况。当某些对象未被使用时,系统就会自动释放这些未被使用对象占用的内存。
如果c++也有这么一种类似机制,当某些new出来的对象不需要使用时,系统可以自动释放这些对象占用的内存。那么在使用c++开发程序时,将会避免很多不必要的错误。因此在android系统中引入了智能指针的概念,其目的也就是想有个像java的垃圾回收机制,可以对不需要的对象进行回收。但是其与java的垃圾回收机制不同的是,智能指针并不需要时刻监视各个对象是否已经可以回收,而是通过引用计数器的方式来判别一个对象是否“存活”。下面对这2种判别对象是否”存活”的方式进行简单描述:
引用计数器算法(智能指针使用的)
给对象添加一个引用计数器,每当有一个引用(在C++中称为句柄)指向该对象时,计数器的值就加1;当引用失效时,计数器进行减1操作;在第一次创建该对象时,会初始化计数器并设置标志位来记录该对象是从无到有的过程;当计数器的值再次回到0时,就需要对该对象进行删除(delete)操作。这种方式实现起来简单,效率也非常高,但不足的是它很难的解决相互循环使用的情况(即对象A中存在指向对象B的指针,对象B中同时存在指向对象A的指针。在需要对他们进行回收时,因为他们都被另一个对象引用而导致无法回收)。解决这个矛盾的一个有效方法就是引入”弱引用”,即为对象创建2个引用计数器,一个强引用计数器,一个弱引用计数器。当强引用计数器的值为0时,不管弱引用计数器的值是否为0,都需要经对象进行回收(delete)操作。当通过弱引用来访问对象时,它必须先被升级成强引用才能访问该对象。根搜索算法(java垃圾回收机制使用的)
基本思路是通过一系列的“GC root”的对象作为起始点,从它们开始向下搜索,搜索走过的路径为引用链,当一个对象到“GC root”没有任何引用链相连接时,则表示该对象是不可用的,它就将被判定为可回收对象,在下次GC操作时被回收。
智能指针是一种能够自己维护对象引用计数的技术,它是一个对象,而不是一个指针。智能指针应用了一个实际的对象,通过它能够自动的维护实际对象的引用计数。
android系统中提供了3种类型的c++智能指针,分别是:
- 轻量级指针:通过简单的引用计数计数维护对象的生命周期
- 强指针:通过强引用计数来维护对象的生命周期
- 弱指针:通过弱引用计数来维护对象的生命周期
1 轻量级指针
轻量级指针通过简单的引用计数计数维护对象的生命周期,如果一个类支持使用轻量级指针,它必须从LightRefBase类继承下来。在该LightRefBase类中提供了一个简单的引用计数器属性。
在frameworks/rs/cpp/util/RefBase.h
下的声明如下:
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 {
/*当引用计数器为0的时候,需要释放该对象占用的内存*/
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:
/*属性mCount用来描述一个对象的引用计数值*/
mutable volatile int32_t mCount;
};
使用智能指针的对象需要继承或者间接继承该类,这样创建出来的对象就具有了对象引用计数mCount这个属性,在后面的使用中,都由对象自己维护该引用计数mCount的值。
轻量级指针类的实现类为sp,通过路径frameworks/rs/cpp/util/StrongPointer.h
查看实现类sp的声明:
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;
};
下面看看实现类sp的析构函数和构造函数具体实现:
template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
{
/*此处调用LightRefBase中的incStrong()方法*/
if (other) other->incStrong(this);
}
template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr)
{
/*此处调用LightRefBase中的incStrong()方法*/
if (m_ptr) m_ptr->incStrong(this);
}
template<typename T>
sp<T>::~sp()
{
/*此处调用LightRefBase中的decStrong()方法,减少指针计算器mCount的值,当mCount值为0的时候会delete掉指针指向的对象*/
if (m_ptr) m_ptr->decStrong(this);
}
使用轻量级智能指针使用方法:
- 直接或间接继承基类LightRefBase;
- 定义类的虚析构函数;
下面定义一个MyClass类,并继承基类LightRefBase,通过MyClass类来展示下轻量级指针的使用。
using namespace android;
/*因为MyClass 继承了基类LightRefBase 所以它也包含了引用计数器mCount*/
class MyClass : public LightRefBase<MyClass>
{
public:
MyClass()
{
printf("involved the constructor!");
}
virtural ~MyClass()
{
printf("destroy the class!");
}
}
int main(int argc,char ** argv)
{
MyClass * p_obj1=new MyClass();
sp<MyClass> p_obj2=p_obj1;/*调用=重载运算,将MyClass对象指针赋值给sp句柄p_obj2的m_ptr属性*/
cout<<"Myclass reference count is:"<<p_obj1->getStrongCount()<<endl;
{
sp<MyClass> p_obj3=p_obj2;/*计数器加1*/
cout<<"MyClass reference count is :"<<p_obj1->getStrongCount()<<endl;
}/*模块结束,会调用p_obj3析构函数,对计数器减1*/
cout<<"Myclass reference count is:"<<p_obj1->getStrongCount()<<endl;
}/*程序结束,会调用p_obj2析构函数,自动将new出来的MyClass对象delete掉*/
轻量级指针可以在确定不会存在相互循环使用的情况使用,否则无法达到”垃圾“自动回收的效果。
2 强指针
强指针和弱指针通过引用计数器来维护指针指向对象的生命周期,而且为了解决相互循环使用的情况,被引用对象需要存储2个引用计数器变量即强引用计数器和弱引用计数器。如果一个对象需要添加引用计数器,就必须直接或间接的继承RefBase类。首先查看下RefBase类的声明,具体如下所示:
class RefBase
{
public:
/*这个方法用来操作强指针的引用计数器加*/
void incStrong(const void* id) const;
/*这个方法用来操作强指针的引用计数器加*/
void decStrong(const void* id) const;
void forceIncStrong(const void* id) const;
//! DEBUGGING ONLY: Get current strong ref count.
int32_t getStrongCount() const;
class weakref_type /*内部类,看名字就知道主要对弱指针进行操作*/
{
public:
RefBase* refBase() const;
/*针对弱指针的引用计数器进行加操作*/
void incWeak(const void* id);
/*针对弱指针的引用计数器进行减操作*/
void decWeak(const void* id);
// acquires a strong reference if there is already one.
bool attemptIncStrong(const void* id);
// acquires a weak reference if there is already one.
// This is not always safe. see ProcessState.cpp and BpBinder.cpp
// for proper use.
bool attemptIncWeak(const void* id);
//! DEBUGGING ONLY: Get current weak ref count.
int32_t getWeakCount() const;
//! DEBUGGING ONLY: Print references held on object.
void printRefs() const;
//! DEBUGGING ONLY: Enable tracking for this object.
// enable -- enable/disable tracking
// retain -- when tracking is enable, if true, then we save a stack trace
// for each reference and dereference; when retain == false, we
// match up references and dereferences and keep only the
// outstanding ones.
void trackMe(bool enable, bool retain);
};
weakref_type* createWeak(const void* id) const;
weakref_type* getWeakRefs() const;
//! DEBUGGING ONLY: Print references held on object.
inline void printRefs() const { getWeakRefs()->printRefs(); }
//! DEBUGGING ONLY: Enable tracking of object.
inline void trackMe(bool enable, bool retain)
{
getWeakRefs()->trackMe(enable, retain);
}
typedef RefBase basetype;
protected:
RefBase();
virtual ~RefBase();
//! Flags for extendObjectLifetime()
enum {
OBJECT_LIFETIME_STRONG = 0x0000,
OBJECT_LIFETIME_WEAK = 0x0001,
OBJECT_LIFETIME_MASK = 0x0001
};
void extendObjectLifetime(int32_t mode);
//! Flags for onIncStrongAttempted()
enum {
FIRST_INC_STRONG = 0x0001
};
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
virtual void onLastWeakRef(const void* id);
private:
friend class ReferenceMover;
static void moveReferences(void* d, void const* s, size_t n,
const ReferenceConverterBase& caster);
private:
friend class weakref_type;
class weakref_impl;
RefBase(const RefBase& o);
RefBase& operator=(const RefBase& o);
/*通过属性mRefs来维护对象的引用计数器,它当中包含了强指针的引用计数器和弱指针引用计数器,所以使用的类weakref_impl来包装它们,任何继承或者间接继承RefBase类的对象都会有该属性(关于c++中子类是否可以继承父类的私有属性,看网上有的人说可以,也有的人说不可以,个人看法是倾向于前者。只是子类虽然继承了父类的私有属性,但是该属性对子类是不可见的,子类只能通过父类提供的公共方法来操作它)*/
weakref_impl* const mRefs;
};
接下来看看weakref_impl类的具体声明。
class RefBase::weakref_impl : public RefBase::weakref_type /*这个类主要用来保存强弱引用计数器*/
{
public:
/*用来描述强指针的引用计数器*/
volatile int32_t mStrong;
/*用来描述强指针的引用计数器*/
volatile int32_t mWeak;
/*属性mBase是指向实际的对象的指针*/
RefBase* const mBase;
/*描述生命周期的控制方式,即 受强指针控制引用计数器控制还是弱指针引用计数器控制等*/
volatile int32_t mFlags;
#if !DEBUG_REFS
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
{
}
void addStrongRef(const void* /*id*/) { }
void removeStrongRef(const void* /*id*/) { }
void renameStrongRefId(const void* /*old_id*/, const void* /*new_id*/) { }
void addWeakRef(const void* /*id*/) { }
void removeWeakRef(const void* /*id*/) { }
void renameWeakRefId(const void* /*old_id*/, const void* /*new_id*/) { }
void printRefs() const { }
void trackMe(bool, bool) { }
#else
weakref_impl(RefBase* base)
: mStrong(INITIAL_STRONG_VALUE)
, mWeak(0)
, mBase(base)
, mFlags(0)
, mStrongRefs(NULL)
, mWeakRefs(NULL)
, mTrackEnabled(!!DEBUG_REFS_ENABLED_BY_DEFAULT)
, mRetain(false)
{
}
~weakref_impl()
{
bool dumpStack = false;
if (!mRetain && mStrongRefs != NULL) {
dumpStack = true;
ALOGE("Strong references remain:");
ref_entry* refs = mStrongRefs;
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
#ifdef MTK_AOSP_ENHANCEMENT
#else
refs->stack.log(LOG_TAG);
#endif
#endif
refs = refs->next;
}
}
if (!mRetain && mWeakRefs != NULL) {
dumpStack = true;
ALOGE("Weak references remain!");
ref_entry* refs = mWeakRefs;
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref);
#if DEBUG_REFS_CALLSTACK_ENABLED
#ifdef MTK_AOSP_ENHANCEMENT
#else
refs->stack.log(LOG_TAG);
#endif
#endif
refs = refs->next;
}
}
if (dumpStack) {
ALOGE("above errors at:");
CallStack stack(LOG_TAG);
}
}
void addStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "addStrongRef: RefBase=%p, id=%p", mBase, id);
addRef(&mStrongRefs, id, mStrong);
}
void removeStrongRef(const void* id) {
//ALOGD_IF(mTrackEnabled,
// "removeStrongRef: RefBase=%p, id=%p", mBase, id);
if (!mRetain) {
removeRef(&mStrongRefs, id);
} else {
addRef(&mStrongRefs, id, -mStrong);
}
}
void renameStrongRefId(const void* old_id, const void* new_id) {
//ALOGD_IF(mTrackEnabled,
// "renameStrongRefId: RefBase=%p, oid=%p, nid=%p",
// mBase, old_id, new_id);
renameRefsId(mStrongRefs, old_id, new_id);
}
#ifdef MTK_AOSP_ENHANCEMENT
void addWeakRef(const void* /*id*/) { }
void removeWeakRef(const void* /*id*/) { }
#else
void addWeakRef(const void* id) {
addRef(&mWeakRefs, id, mWeak);
}
void removeWeakRef(const void* id) {
if (!mRetain) {
removeRef(&mWeakRefs, id);
} else {
addRef(&mWeakRefs, id, -mWeak);
}
}
#endif
void renameWeakRefId(const void* old_id, const void* new_id) {
renameRefsId(mWeakRefs, old_id, new_id);
}
void trackMe(bool track, bool retain)
{
mTrackEnabled = track;
mRetain = retain;
}
void printRefs() const
{
String8 text;
{
Mutex::Autolock _l(mMutex);
char buf[128];
sprintf(buf, "Strong references on RefBase %p (weakref_type %p):\n", mBase, this);
text.append(buf);
printRefsLocked(&text, mStrongRefs);
sprintf(buf, "Weak references on RefBase %p (weakref_type %p):\n", mBase, this);
text.append(buf);
printRefsLocked(&text, mWeakRefs);
}
{
char name[100];
snprintf(name, 100, DEBUG_REFS_CALLSTACK_PATH "/%p.stack", this);
int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
if (rc >= 0) {
write(rc, text.string(), text.length());
close(rc);
ALOGD("STACK TRACE for %p saved in %s", this, name);
}
else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
name, strerror(errno));
}
}
private:
struct ref_entry
{
ref_entry* next;
const void* id;
#if DEBUG_REFS_CALLSTACK_ENABLED
CallStack stack;
#endif
int32_t ref;
};
void addRef(ref_entry** refs, const void* id, int32_t mRef)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* ref = new ref_entry;
// Reference count at the time of the snapshot, but before the
// update. Positive value means we increment, negative--we
// decrement the reference count.
ref->ref = mRef;
ref->id = id;
#if DEBUG_REFS_CALLSTACK_ENABLED
ref->stack.update(2);
#endif
ref->next = *refs;
*refs = ref;
}
}
void removeRef(ref_entry** refs, const void* id)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* const head = *refs;
ref_entry* ref = head;
while (ref != NULL) {
if (ref->id == id) {
*refs = ref->next;
delete ref;
return;
}
refs = &ref->next;
ref = *refs;
}
ALOGE("RefBase: removing id %p on RefBase %p"
"(weakref_type %p) that doesn't exist!",
id, mBase, this);
ref = head;
while (ref) {
char inc = ref->ref >= 0 ? '+' : '-';
ALOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref);
ref = ref->next;
}
CallStack stack(LOG_TAG);
}
}
void renameRefsId(ref_entry* r, const void* old_id, const void* new_id)
{
if (mTrackEnabled) {
AutoMutex _l(mMutex);
ref_entry* ref = r;
while (ref != NULL) {
if (ref->id == old_id) {
ref->id = new_id;
}
ref = ref->next;
}
}
}
void printRefsLocked(String8* out, const ref_entry* refs) const
{
char buf[128];
while (refs) {
char inc = refs->ref >= 0 ? '+' : '-';
sprintf(buf, "\t%c ID %p (ref %d):\n",
inc, refs->id, refs->ref);
out->append(buf);
#if DEBUG_REFS_CALLSTACK_ENABLED
out->append(refs->stack.toString("\t\t"));
#else
out->append("\t\t(call stacks disabled)");
#endif
refs = refs->next;
}
}
mutable Mutex mMutex;
ref_entry* mStrongRefs;
ref_entry* mWeakRefs;
bool mTrackEnabled;
// Collect stack traces on addref and removeref, instead of deleting the stack references
// on removeref that match the address ones.
bool mRetain;
#endif
};
在该类中代码虽然比较长,但是有用的就 volatile int32_t mStrong; volatile int32_t mWeak;
2个属性而已,其他都是和调试相关的信息了。在类的构造函数中可以看到,会将把属性mStrong置为INITIAL_STRONG_VALUE(#define INITIAL_STRONG_VALUE (1<<28)
),个人理解,这应该是做一个标识而已,记录该对象是刚创建的,在第一次对属性mStrong操作时会消除该标志位。
强指针的实现类sp,在前面的轻量级指针已经见过了。其具体声明如下:
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;
};
在它的构造函数和析构函数中分别会调用操作强指针引用计数器的方法incStrong()和decStrong()。这2个是在RefBase类中声明的,具体实现如下:
void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs; /*mRefs属性是个指针,指向weakref_impl类型的对象,该对象里面存储了强弱引用计数器*/
/*首先会将弱指针引用计数器加操作*/
refs->incWeak(id);
refs->addStrongRef(id);
const int32_t c = refs->mStrong.fetch_add(1, std::memory_order_relaxed);
ALOG_ASSERT(c > 0, "incStrong() called on %p after last strong ref", refs);
#if PRINT_REFS
ALOGD("incStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
/*判断强指针引用计数器是否从来没用过,如果之前都没用过该计数器,就需要将该计数器调整为1*/
if (c != INITIAL_STRONG_VALUE) {
return;
}
int32_t old = refs->mStrong.fetch_sub(INITIAL_STRONG_VALUE,
std::memory_order_relaxed);
// A decStrong() must still happen after us.
ALOG_ASSERT(old > INITIAL_STRONG_VALUE, "0x%x too small", old);
refs->mBase->onFirstRef();
}
void RefBase::decStrong(const void* id) const
{
weakref_impl* const refs = mRefs;
refs->removeStrongRef(id);
const int32_t c = refs->mStrong.fetch_sub(1, std::memory_order_release);
#if PRINT_REFS
ALOGD("decStrong of %p from %p: cnt=%d\n", this, id, c);
#endif
ALOG_ASSERT(c >= 1, "decStrong() called on %p too many times", refs);
if (c == 1) {
std::atomic_thread_fence(std::memory_order_acquire);
refs->mBase->onLastStrongRef(id);
int32_t flags = refs->mFlags.load(std::memory_order_relaxed);
if ((flags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) { /*如果强引用计数器的值变为了0,且是规则是受强引用控制,则delete被引用的对象*/
delete this;
// Since mStrong had been incremented, the destructor did not
// delete refs.
}
}
// Note that even with only strong reference operations, the thread
// deallocating this may not be the same as the thread deallocating refs.
// That's OK: all accesses to this happen before its deletion here,
// and all accesses to refs happen before its deletion in the final decWeak.
// The destructor can safely access mRefs because either it's deleting
// mRefs itself, or it's running entirely before the final mWeak decrement.
refs->decWeak(id);
}
3 弱指针
从上面可以看到,如在对强引用计数器进行+1操作是,弱引用计数器也会相应的做+1操作。而在弱指针类中更多的只是对被引用对象中的弱引用计数器进行操作,它的设计就是为了解决循环使用的情况,该类的具体声明如下:
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;
T* m_ptr;
weakref_type* weakref_type;
};
从声明中可以看到,和sp有如下不同的地方:
- 除了指向目标对象的指针外,还有一个属性weakref_type,它是个weakref_type类型指针,用来指向引用计数器对象。
- 没有重载
->
,*
等运算符。 - 有一个promote方法,用来将弱引用指针升级为强引用指针。
- 被引用对象的必须继承RefBase类。
在它的构造函数中,有如下的实现:
template<typename T>
wp<T>::wp(T* other)
: m_ptr(other)
{
if (other) m_refs = other->createWeak(this);/*对属性m_refs进行赋值操作*/
}
在该实现中,只是调用了 RefBase类中的createWeak函数,从名字上看是创建弱引用计数器,然后看看createWeak函数的实现:
RefBase::weakref_type* RefBase::createWeak(const void* id) const
{
mRefs->incWeak(id);
return mRefs;
}
void RefBase::weakref_type::incWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this); /*此处的this指针实际上就是mRefs*/
impl->addWeakRef(id);
const int32_t c __unused = android_atomic_inc(&impl->mWeak);/*增加弱引用计数器mWeak的值 */
ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);
}
从整个过程来看,实际上就是在构造wp时,将被引用对象中的弱引用计数器变为1。 如果后面还有其他wp指向该对象时,弱引用计数器的值还会继续增加。
4 总结
智能指针就是为了在后面使用c++语言进行程序开发时,可以将更多的时间花在程序业务逻辑上,而不需要去担心c++语言中是否存在野指针、内存泄露等问题。所以使用智能指针进行开发并不是必须的,它只是为了方便程序员进行开发而已,磨刀不误砍柴工,其实在android系统内部,智能指针使用还是非常广泛的,而且它的实现简单,使用简便,如果程序员在后面使用它来辅助c++程序开发将会强大很多。
在智能指针框架的设计和实现上:
- 主要是需要为被引用对象添加一个计数器,由它自己来记录和管理本身被引用的次数,并且在计数器值为0的时候,释放自己。
- 对计数器的操作主要由智能指针sp或者wp触发,即当有智能指针指向该对象时,引用计数器就执行+1操作,指向该对象的智能指针指失效时,执行-1操作。
- RefBase类的设计比较复杂而且里面有很多和调试相关的逻辑,其实可以简单理解,该类主要维护引用计数器(总共2个,一个弱引用计数器,一个强引用计数器),并提供对该计数器进行操作的函数。
参考:《深入理解android内核设计思想》、《android系统源代码情景分析》、《深入理解Java虚拟机》