安卓智能指针
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++中的智能指针unique_ptr系列-- unique_ptr的get()赋给普通指针后的崩溃(其实是生命周期惹的祸)