安卓智能指针

Posted xuguoli_beyondboy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓智能指针相关的知识,希望对你有一定的参考价值。

为什么要安卓智能指针

在安卓系统中,为提高运行效率,其框架中间层很多是采用c++和c语言去实现的,在这实现过程,必定会应用不少地指针操作,同时c++和c不想Java那样有垃圾自动回收功能,因此会使程序员在某些操作常常遇到一些如下的问题:

  • 忘记指针初始化,这是指针在程序执行过程中,会随机指向某个地址,一旦这个地址是程序或系统核心部分,容易引起数据错误或系统崩溃等错误(这个问题很好解决,将指针默认设置为null。)。
  • new 对象之后没有及时delete:该对象占用的内存空间没有及时的回收,使得系统可用的内存空间越来越少,很有可能最终导致内存溢出,出现崩溃
  • 野指针:ptr=new Object ,创建了一个对象Object,且指针ptr指向它,当Object使用结束之后也delete了,但是没有做的操作就是没有将ptr清空,这样ptr仍然指向了该Object对象的地址。结果在使用时ptr不为空,可以使用,但是此时Object对象已经delete了,Object所在的地址上的对象可能已经发生了变化,还用ptr访问的话就可能出现未知错误。

在C++语言中,我们可以通过手动释放对象的内存空间,但是对于指针操作来说,释放对象内存空间的同时,又得避免出现野指针的现象,因此控制程序在何时候释放一个对象内存就显得尤为重要了(虽然c++11也提供三种智能指针,但三种都存在一定局限性,不太符合安卓的使用,因此需要针对安卓来开发一套智能指针来管理对象)。根据这些特点我们可以通过引用计数的方法来实现这目的。
引用计数实现:
我们可以让一个对象对应用它的指针进行统计,并且这个变量保存中这个对象中,当计数为0时,就通过delete删除这个对象,那么怎么实现在指针赋值时候就统计引用呢?答案就是通过c++运算符重载的模式和c++析构函数来实现这目的,具体伪代码实现如下:

//自定义智能指针
template <typename T>
class SmartPointer

 //初始化时将m_ptr设置为空,这样第一个问题就解决了
 inline SmartPointer(): m_ptr(0)
 //虚构函数
  ~wp();  
  //重载赋值操作符
  SmartPointer& operator = (T* other); 
 private:
     T* m_ptr;//保存object对象的地址


//重载赋值操作符的实现
SmartPointer<T> &SmartPointer<T>::operator=(T* other)

          if(other!=null)
          
               m_ptr=other;//指向该对象other
               other->incStrong();//other引用计数加一
          
          return *this;

//虚构函数的实现
wp<T>::~wp()

     if(m_ptr) m_ptr-<decStrong();

//被智能指针指向的对象要继承的父类实现
template <class T>
class LightRefBase

public:
     inline LightRefBase():mCount(0)
     inline void incStrong() const//引用计数加一
     
          android_atomic_inc(&mCount);
     
     inline void decStrong() const//引用计数减一
     
          if(android_atomic_dec(&mCount)==1)
          
               delete static_cast<const T*>(this);//如果没有被引用就直接删除该对象
                    

     
private:
     mutable volatile int32_t mCount;//引用计数的个数

可以看出被智能指针引用的对象要继承于LightRefBase类,且智能指针SmartPointer是通过重载赋值操作符和虚构函数实现自动的管理对象引用计数,其关系如图所示:

以下是简单的使用代码:

//假设Class是一个继承了LightRefBase的类,这里创建一个Class对象
Class class=new Class();
//定义一个指向Class对象的智能指针
SmartPointer <Class> sp;//由于里面已经对指针进行初始化,故这里不用初始化
//智能指向了class,故class里面的引用计数加一
sp=class;
//释放智能指针对象同时引用计数会减一,如果引用计数刚好为零,则删除释放引用对象的内存
sp=NULL;//切记删除智能指针不要用delete sp

安卓智能指针

在android应用中,android实现了两种智能指针,分别是Strong Pointer(强指针,简称sp)和Weak Pointer(弱指针,简称wp),智能强指针一般来控制对象的强引用,而智能弱指针一般来控制两者对象互相引用等现象。
强指针sp:
其实android sp实现原理和上面的Smart Pointer实现基本类似,都是直接对引用计数的加一或者减一。
源码实现:

template<typename T>
sp<T>::sp(T* other)
: m_ptr(other)
  
    if (other) other->incStrong(this);
  

template<typename T>
sp<T>::sp(const sp<T>& other)
: m_ptr(other.m_ptr)
  
    if (m_ptr) m_ptr->incStrong(this);
  

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>
sp<T>::~sp()

    if (m_ptr) m_ptr->decStrong(this);

//重载赋值操作
template<typename T>
sp<T>& sp<T>::operator = (const sp<T>& other) 
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherPtr->incStrong(this);//将被sp指针指向otherPtr对象的引用计数加1
    if (m_ptr) m_ptr->decStrong(this);//被sp指向的原来对象m_ptr引用计数减一
    m_ptr = otherPtr;//更改指针为指向otherPtr对象
    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 = (U* other)

    if (other) ((T*)other)->incStrong(this);
    if (m_ptr) m_ptr->decStrong(this);
    m_ptr = other;
    return *this;


template<typename T>
void sp<T>::force_set(T* other)

    other->forceIncStrong(this);
    m_ptr = other;


template<typename T>
//重新初始化指向对象的指针
void sp<T>::clear()

    if (m_ptr) 
        m_ptr->decStrong(this);
        m_ptr = 0;
    


template<typename T>
void sp<T>::set_pointer(T* ptr) 
    m_ptr = ptr;


template <typename T>
inline TextOutput& operator<<(TextOutput& to, const sp<T>& val)

    return printStrongPointer(to, val.get());


; // namespace RSC
;

不过要满足sp的对象,需要其对象继承类上面LightRefBase类,否则sp对其不到应用作用了。
弱指针wp:
再看wp弱引用,已经有了强引用,为什么还要用弱引用呢?假如现在又两个类:CDad,CChild,其代码如下:

struct CDad

     CChild *myChild;


Struct CChild

     CDad *myDad;

这种情况虽然少见,但也不是不会发生,这两者关系如图:

这样就处于死锁状态,两者都处于被需要状态,不能被释放,这个时候就出现了弱引用,具体做法:CDad使用强指针引用CChild对象,而CChild只能使用弱引用指向CDad。规定当强引用计数为0时,不管弱引用是否为0都要delete自己,一旦delete自己就能打破僵局,避免死锁的出现。
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;//将wp转换为sp函数

    // 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*   m_refs;//指向weakref_type类型的对象
;

//传入一个符合条件的对象时,并赋值给m_ptr
template<typename T>
wp<T>::wp(T* other)
    : m_ptr(other)
 
    if (other) m_refs = other->createWeak(this);//创建弱引用,其实就是后面说的weakref_impl对象

//传入智能弱指针,并赋值给m_ptr和m_refs
template<typename T>
wp<T>::wp(const wp<T>& other)
    : m_ptr(other.m_ptr), m_refs(other.m_refs)

    if (m_ptr) m_refs->incWeak(this);//弱引用计数加1


//传入智能强指针,并赋值给m_ptrg
template<typename T>
wp<T>::wp(const sp<T>& other)
    : m_ptr(other.m_ptr)

    if (m_ptr) 
        m_refs = m_ptr->createWeak(this);
    

//与上面一样
template<typename T> template<typename U>
wp<T>::wp(U* other)
    : m_ptr(other)

    if (other) m_refs = other->createWeak(this);


template<typename T> template<typename U>
wp<T>::wp(const wp<U>& other)
    : m_ptr(other.m_ptr)

    if (m_ptr) 
        m_refs = other.m_refs;
        m_refs->incWeak(this);
    


template<typename T> template<typename U>
wp<T>::wp(const sp<U>& other)
    : m_ptr(other.m_ptr)

    if (m_ptr) 
        m_refs = m_ptr->createWeak(this);
    


template<typename T>
wp<T>::~wp()

    if (m_ptr) m_refs->decWeak(this);//引用计数器减一


//指向新的引用对象时
template<typename T>
wp<T>& wp<T>::operator = (T* other)

    //如果other为空,则弱引用计数初始化为0,并强引用也设为空
    weakref_type* newRefs =
        other ? other->createWeak(this) : 0;
    if (m_ptr) m_refs->decWeak(this);//原来引用计数减一
    m_ptr = other;
    m_refs = newRefs;
    return *this;


template<typename T>
wp<T>& wp<T>::operator = (const wp<T>& other)

    weakref_type* otherRefs(other.m_refs);
    T* otherPtr(other.m_ptr);
    if (otherPtr) otherRefs->incWeak(this);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = otherRefs;
    return *this;


template<typename T>
wp<T>& wp<T>::operator = (const sp<T>& other)

    weakref_type* newRefs =
        other != NULL ? other->createWeak(this) : NULL;
    T* otherPtr(other.m_ptr);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = newRefs;
    return *this;


template<typename T> template<typename U>
wp<T>& wp<T>::operator = (U* other)

    weakref_type* newRefs =
        other ? other->createWeak(this) : NULL;
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = other;
    m_refs = newRefs;
    return *this;


template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const wp<U>& other)

    weakref_type* otherRefs(other.m_refs);
    U* otherPtr(other.m_ptr);
    if (otherPtr) otherRefs->incWeak(this);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = otherRefs;
    return *this;


template<typename T> template<typename U>
wp<T>& wp<T>::operator = (const sp<U>& other)

    weakref_type* newRefs =
        other != NULL ? other->createWeak(this) : NULL;
    U* otherPtr(other.m_ptr);
    if (m_ptr) m_refs->decWeak(this);
    m_ptr = otherPtr;
    m_refs = newRefs;
    return *this;


//设置强引用和弱引用
template<typename T>
void wp<T>::set_object_and_refs(T* other, weakref_type* refs)

    if (other) refs->incWeak(this);//新的弱引用计数器增一
    if (m_ptr) m_refs->decWeak(this);//原来的弱引用计数器减一
    m_ptr = other;
    m_refs = refs;


//将弱引用转换为强引用
template<typename T>
sp<T> wp<T>::promote() const

    sp<T> result;
    if (m_ptr && m_refs->attemptIncStrong(&result)) 
        result.set_pointer(m_ptr);
    
    return result;


template<typename T>
//重置
void wp<T>::clear()

    if (m_ptr) 
        m_refs->decWeak(this);
        m_ptr = 0;
    

1 除了指向目标对象的m_ptr还有一个指向weakref_type类型的对象,weakref_type是用来管理wp的类,由weakref_impl子类实现。
2 一个的方法就是promote方法,可以将wp升级为sp。
3 这里的目标对象不再是sp中的LightRefBase,而是其父类RefBase,这个父类不仅仅需要处理sp的情况,还要处理wp的情况。
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 //嵌套类,wp中的m_refs就引用到这个类
    
    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);
        //指向弱引用变量
        weakref_impl* const mRefs;
;

RefBase::RefBase()
    : mRefs(new weakref_impl(this))//构造方法创建了weakref_impl对象


//虚构函数的具体实现
RefBase::~RefBase()

    if (mRefs->mStrong == INITIAL_STRONG_VALUE) 
        // we never acquired a strong (and/or weak) reference on this object.
        delete mRefs;
     else 
        // life-time of this object is extended to WEAK or FOREVER, in
        // which case weakref_impl doesn't out-live the object and we
        // can free it now.
        if ((mRefs->mFlags & OBJECT_LIFETIME_MASK) != OBJECT_LIFETIME_STRONG) 
            // It's possible that the weak count is not 0 if the object
            // re-acquired a weak reference in its destructor
            if (mRefs->mWeak == 0) 
                delete mRefs;
            
        
    
    // for debugging purposes, clear this.
    const_cast<weakref_impl*&>(mRefs) = NULL;

从源码可以知道,RefBase嵌套了weakref_type类,也就是wp维护该类型的一个字段 m_refs,但RefBase也维护一个weakref_impl类型的字段mRefs,从名字可以看出weakref_impl应该是weakref_type的类具体实现,其部分源码(system\\core\\libutils\\RefBase.cpp)如下:

class RefBase::weakref_impl : public RefBase::weakref_type

public:
    volatile int32_t    mStrong;//强引用计数值
    volatile int32_t    mWeak;//弱引用计数值
    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)//强引用计数INITIAL_STRONG_VALUE 等于0x1000000 
        , mWeak(0)//弱引用计数初始化为0
        , mBase(base)//保存传入的base值,就是目标对象
        , mFlags(0)//保存生命周期标志,默认为Strong  
        , 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
                refs->stack.log(LOG_TAG);
#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
                refs->stack.log(LOG_TAG);
#endif
                refs = refs->next;
            
        
        if (dumpStack) 
            ALOGE("above errors at:");
            CallStack stack(LOG_TAG);
        
    
    

从源码分析我们知道,强引用和若引用计数器在weakref_iml实现类中,而RefBase类中又维护其m_refs,其关系如图所示:

和LightRefBase不同,RefBase不是直接使用int变量来保存引用计数值,而是采用了weakref_type类型的计数器,这是用于RefBase要处理弱引用和强引用两种计数类型。另外,wp中也同时保存了这个计数器的地址,也就是wp中的m_refs和RefBase中的mRefs都指向了计数器,其中wp是通过在构造函数中调用目标对象的createWeak来获得计数器地址,而计数器本身是由RefBase在构造是创建的。
首先我们看RefBase中的createWeak() ,因为它的子类对象一旦复制给wp,就会在wp的构造函数调用createWeak() 付给弱引用,具体实现如下:

RefBase::weakref_type* RefBase::createWeak(const void* id) const

    mRefs->incWeak(id);//增加弱引用计数
    return mRefs;

从上面的方法知道在返回弱引用的同时,通过incWeak()增加弱引用的计数,其具体实现:

void RefBase::weakref_type::incWeak(const void* id)

    weakref_impl* const impl = static_cast<weakref_impl*>(this);//获取保存这个对象的计数器的weakref_impl
    impl->addWeakRef(id);//
    const int32_t c __unused = android_atomic_inc(&impl->mWeak);//增加弱引用
    ALOG_ASSERT(c >= 0, "incWeak called on %p after last weak ref", this);//打印出最后一个对该对象弱引用提示

相对于wp引用RefBase子类对象来说,sp引用RefBase子类对象会通过调用incStrong 方法来增加强引用计数值,其具体实现如下:

void RefBase::incStrong(const void* id) const

    weakref_impl* const refs = mRefs;
    refs->incWeak(id);//增加弱引用计数值
    refs->addStrongRef(id););//调试使用,非调试没有具体操作
    //增加强引用,并返回原来的值,其mStrong的值初始化为0x1000000,增加以后就是0x1000001
    const int32_t c = android_atomic_inc(&refs->mStrong);//增加强引用计数值
    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
    //如果不是第一次调用,就直接返回
    if (c != INITIAL_STRONG_VALUE)  
        return;
    
    //进行相加操作,即相当于0x1000001-0x1000000=1
    android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
    //首次引用的回掉,此方法体默认为空,需自己去实现
    refs->mBase->onFirstRef();

从其方法分析知道,当sp指向继承RefBase对象时,不仅强引用计数值增一,弱引用计数值也会增一。
既然有增加引用计数值得方法,那么一定也有减少引用计数值的方法,其那就是decStrong()decWeak() 两个方法,一个是减少强引用计数值,另一个是减少弱引用计数值,其decStrong()具体实现如下:

void RefBase::decStrong(const void* id) const

    weakref_impl* const refs = mRefs;
    refs->removeStrongRef(id);//调试目的
    //减少强引用计数值,并返回强引用原计数值
    const int32_t c = android_atomic_dec(&refs->mStrong);
#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) 
        //回调此方法,此方法体也为空,需要子类实现
        refs->mBase->onLastStrongRef(id);
        //进行掩码运算,判断是否为强引用
        if ((refs->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_STRONG) 
            delete this;//删除对象
        
    
    refs->decWeak(id);//并删除弱引用

结合上面两部分源码,我们发现一个规律,就是sp引用RefBase子类对象时,该子类对象调用incStrong()decStrong() 时,强引用和弱引用计数值要么都增一要么都减一,一一匹配。
decWeak() 具体实现:

void RefBase::weakref_type::decWeak(const void* id)

    weakref_impl* const impl = static_cast<weakref_impl*>(this);
    impl->removeWeakRef(id);//调试使用
    //减少弱应用计数值,并返回弱引用计数原值
    const int32_t c = android_atomic_dec(&impl->mWeak);
    ALOG_ASSERT(c >= 1, "decWeak called on %p too many times", this);
    //如果弱引用还不是最后一个,则返回
    if (c != 1) return;
     //判断标记释放规则是否受强引用控制的,还是仅依赖弱引用
    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_STRONG) 
        // This is the regular lifetime case. The object is destroyed
        // when the last strong reference goes away. Since weakref_impl
        // outlive the object, it is not destroyed in the dtor, and
        // we'll have to do it here.
        if (impl->mStrong == INITIAL_STRONG_VALUE) 
            // Special case: we never had a strong reference, so we need to
            // destroy the object now.
            //如果该对象从来没有被强引用,则用这种方式删除对象,否则用下面的方式删除
            delete impl->mBase;
         else 
            // ALOGV("Freeing refs %p of old RefBase %p\\n", this, impl->mBase);
            delete impl;
        
     else 
        // less common case: lifetime is OBJECT_LIFETIME_WEAK|FOREVER
        impl->mBase->onLastWeakRef(id);
        if ((impl->mFlags&OBJECT_LIFETIME_MASK) == OBJECT_LIFETIME_WEAK) 
            // this is the OBJECT_LIFETIME_WEAK case. The last weak-reference
            // is gone, we can destroy the object.
            delete impl->mBase;
        
    

从上面部分看来mFlags 这个标记对智能指针管理对象有很大的影响,其默认值为0(即OBJECT_LIFETIME_STRONG),但可以通过下面来更改其引用控制规则:

void RefBase::extendObjectLifetime(int32_t mode)

    android_atomic_or(mode, &mRefs->mFlags);//or运算

使用安卓智能指针简单实例

定义一个符合被安卓智能指针可引用的类,具体代码如下:

//该类继承了RefBase
class Test:public RefBase



int main()

    Test * test=new Test();
    sp<Test> spTest(test);//强引用test对象,这是强引用计数值加一,弱引用计数值也加一,即mStrong=1,mWeak=1
    wp<Test> wpTest(test);//弱引用test对象,这是只有弱引用计数值加一,即mStrong=1,mWeak=2
    //下面不要通过delete指针对象方式释放对象,因为其sp和wp都通过重载了`=` 操作符来管理引用的
    spTest=null;//这是mStrong=0,mWeak=1, 如果是test标记是为强引用控制,则释放该对象,但还没有释放内部weakref_impl对象
    wpTest=null;//mWeak=0,释放了内部weakref_impl对象

总结:

  • 安卓智能指针分为强指针sp和弱指针 wp两种。
  • 一般来说目标对象的父类是RefBase,因为其存储了强引用和弱引用两种类型的计数值。
  • 当sp引用目标对象时,强引用和弱引用计数值都会加一。
  • 当wp引用目标对象时,只有弱引用计数值会加一。
  • 使用者可以通过extendObjectLifetime()方法来更改智能指针管理对象的规则,不同规则下对删除目标对象的时机判断也是不一样的。
    参考资料:

http://blog.csdn.net/yujun411522/article/details/46624583#

以上是关于安卓智能指针的主要内容,如果未能解决你的问题,请参考以下文章

c++智能指针介绍_再补充

c++中的智能指针

再探 智能指针

如何防止智能指针循环引用问题

实战c++中的智能指针unique_ptr系列-- unique_ptr的get()赋给普通指针后的崩溃(其实是生命周期惹的祸)

如何在类层次结构中传递智能指针