仿xss网站搭建,官方网站下载游戏,h5开发wordpress客户端,什么身一什么网站建设提供引用计数器的类RefBase我们就暂时介绍到这里#xff0c;后面我们再结合智能指针类一起分析#xff0c;现在先来看看强指针类和弱指针类的定义。强指针类的定义我们在前面介绍轻量级指针的时候已经见到了#xff0c;就是sp类了#xff0c;这里就不再把它的代码列出来了。…提供引用计数器的类RefBase我们就暂时介绍到这里后面我们再结合智能指针类一起分析现在先来看看强指针类和弱指针类的定义。强指针类的定义我们在前面介绍轻量级指针的时候已经见到了就是sp类了这里就不再把它的代码列出来了。我们来看看它的构造函数的实现templatesp::sp(T* other): m_ptr(other){if (other) other-incStrong(this);}这里传进来的参数other一定是继承于RefBase类的因此在函数的内部它调用的是RefBase类的incStrong函数它定义在frameworks/base/libs/utils/RefBase.cpp文件中void RefBase::incStrong(const void* id) const{weakref_impl* const refs mRefs;refs-addWeakRef(id);refs-incWeak(id);refs-addStrongRef(id);const int32_t c android_atomic_inc(refs-mStrong);LOG_ASSERT(c 0, incStrong() called on %p after last strong ref, refs);#if PRINT_REFSLOGD(incStrong of %p from %p: cnt%d\n, this, id, c);#endifif (c ! INITIAL_STRONG_VALUE) {return;}android_atomic_add(-INITIAL_STRONG_VALUE, refs-mStrong);const_cast(this)-onFirstRef();}成员变量mRefs是在RefBase类的构造函数中创建的RefBase::RefBase(): mRefs(new weakref_impl(this)){// LOGV(Creating refs %p with RefBase %p\n, mRefs, this);}在这个incStrong函数中主要做了三件事情一是增加弱引用计数refs-addWeakRef(id);refs-incWeak(id);二是增加强引用计数refs-addStrongRef(id);const int32_t c android_atomic_inc(refs-mStrong);三是如果发现是首次调用这个对象的incStrong函数就会调用一个这个对象的onFirstRef函数让对象有机会在对象被首次引用时做一些处理逻辑if (c ! INITIAL_STRONG_VALUE) {return;}android_atomic_add(-INITIAL_STRONG_VALUE, refs-mStrong);const_cast(this)-onFirstRef();这里的c返回的是refs-mStrong加1前的值如果发现等于INITIAL_STRONG_VALUE就说明这个对象的强引用计数是第一次被增加因此refs-mStrong就是初始化为INITIAL_STRONG_VALUE的它的值为#define INITIAL_STRONG_VALUE (128)这个值加1后等于128 1不等于1因此后面要再减去-INITIAL_STRONG_VALUE于是refs-mStrong就等于1了就表示当前对象的强引用计数值为1了这与这个对象是第一次被增加强引用计数值的逻辑是一致的。回过头来看弱引用计数是如何增加的首先是调用weakref_impl类的addWeakRef函数我们知道在Release版本中这个函数也不做而在Debug版本中这个函数增加了一个ref_entry对象到了weakref_impl对象的mWeakRefs列表中表示此weakref_impl对象的弱引用计数被增加了一次。接着又调用了weakref_impl类的incWeak函数真正增加弱引用计数值就是在这个函数实现的了weakref_impl类的incWeak函数继承于其父类weakref_type的incWeak函数void RefBase::weakref_type::incWeak(const void* id){weakref_impl* const impl static_cast(this);impl-addWeakRef(id);const int32_t c android_atomic_inc(impl-mWeak);LOG_ASSERT(c 0, incWeak called on %p after last weak ref, this);}增加弱引用计数是下面语句执行的constint32_t c android_atomic_inc(impl-mWeak);但是前面为什么又调用了一次addWeakRef函数呢前面不是已经调用过了吗在Release版本中因为weakref_impl类的addWeakRef函数是空实现这里再调用一次没有什么害处但是如果在Debug版本岂不是冗余了吗搞不清有人问过负责开发Android系统Binder通信机制模块的作者Dianne Hackborn这个问题他是这样回答的Ah I see. Well the debug code may be broken, though I wouldnt leap to thatconclusion without actually testing it; I know it has been used in thepast. Anyway, these things get compiled out in non-debug builds, so thereis no reason to change them unless you are actually trying to use this debugcode and it isnt working and need to do this to fix it.既然他也不知道怎么回事我们也不必深究了知道有这么回事就行。这里总结一下强指针类sp在其构造函数里面所做的事情就是分别为目标对象的强引用计数和弱引和计数增加了1。再来看看强指针类的析构函数的实现templatesp::~sp(){if (m_ptr) m_ptr-decStrong(this);}同样这里的m_ptr指向的目标对象一定是继承了RefBase类的因此这里调用的是RefBase类的decStrong函数这也是定义在frameworks/base/libs/utils/RefBase.cpp文件中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_REFSLOGD(decStrong of %p from %p: cnt%d\n, this, id, c);#endifLOG_ASSERT(c 1, decStrong() called on %p too many times, refs);if (c 1) {const_cast(this)-onLastStrongRef(id);if ((refs-mFlagsOBJECT_LIFETIME_WEAK) ! OBJECT_LIFETIME_WEAK) {deletethis;}}refs-removeWeakRef(id);refs-decWeak(id);}这里的refs-removeStrongRef函数调用语句是对应前面在RefBase::incStrong函数里的refs-addStrongRef函数调用语句的在Release版本中这也是一个空实现函数真正实现强引用计数减1的操作是下面语句const int32_t c android_atomic_dec(refs-mStrong);如果发现减1前此对象的强引用计数为1就说明从此以后就再没有地方引用这个目标对象了这时候就要看看是否要delete这个目标对象了if (c 1) {const_cast(this)-onLastStrongRef(id);if ((refs-mFlagsOBJECT_LIFETIME_WEAK) ! OBJECT_LIFETIME_WEAK) {deletethis;}}在强引用计数为0的情况下如果对象的标志位OBJECT_LIFETIME_WEAK被设置了就说明这个对象的生命周期是受弱引用计数所控制的因此这时候就不能delete对象要等到弱引用计数也为0的情况下才能delete这个对象。接下来的ref-removeWeakRef函数调用语句是对应前面在RefBase::incStrong函数里的refs-addWeakRef函数调用语句的在Release版本中这也是一个空实现函数真正实现强引用计数减1的操作下面的refs-decWeak函数weakref_impl类没有实现自己的decWeak函数它继承了weakref_type类的decWeak函数void RefBase::weakref_type::decWeak(const void* id){weakref_impl* const impl static_cast(this);impl-removeWeakRef(id);const int32_t c android_atomic_dec(impl-mWeak);LOG_ASSERT(c 1, decWeak called on %p too many times, this);if (c ! 1) return;if ((impl-mFlagsOBJECT_LIFETIME_WEAK) ! OBJECT_LIFETIME_WEAK) {if (impl-mStrong INITIAL_STRONG_VALUE)deleteimpl-mBase;else{// LOGV(Freeing refs %p of old RefBase %p\n, this, impl-mBase);deleteimpl;}} else{impl-mBase-onLastWeakRef(id);if ((impl-mFlagsOBJECT_LIFETIME_FOREVER) ! OBJECT_LIFETIME_FOREVER) {deleteimpl-mBase;}}}这里又一次调用了weakref_impl对象的removeWeakRef函数这也是和RefBase::weakref_type::incWeak函数里面的impl-addWeakRef语句所对应的实现弱引用计数减1的操作是下面语句constint32_t c android_atomic_dec(impl-mWeak);减1前如果发现不等于1那么就什么也不用做就返回了如果发现等于1就说明当前对象的弱引用计数值为0了这时候就要看看是否要delete这个对象了if ((impl-mFlagsOBJECT_LIFETIME_WEAK) ! OBJECT_LIFETIME_WEAK) {if (impl-mStrong INITIAL_STRONG_VALUE)deleteimpl-mBase;else{// LOGV(Freeing refs %p of old RefBase %p\n, this, impl-mBase);deleteimpl;}} else{impl-mBase-onLastWeakRef(id);if ((impl-mFlagsOBJECT_LIFETIME_FOREVER) ! OBJECT_LIFETIME_FOREVER) {deleteimpl-mBase;}}如果目标对象的生命周期是不受弱引用计数控制的就执行下面语句if (impl-mStrong INITIAL_STRONG_VALUE)deleteimpl-mBase;else{// LOGV(Freeing refs %p of old RefBase %p\n, this, impl-mBase);deleteimpl;}这个代码段是什么意思呢这里是减少对象的弱引用计数的地方如果调用到这里那么就说明前面一定有增加过此对象的弱引用计数而增加对象的弱引用计数有两种场景的一种场景是增加对象的强引用计数的时候会同时增加对象的弱引用计数另一种场景是当我们使用一个弱指针来指向对象时在弱指针对象的构造函数里面也会增加对象的弱引用计数不过这时候就只是增加对象的弱引用计数了并没有同时增加对象的强引用计数。因此这里在减少对象的弱引用计数时就要分两种情况来考虑。如果是前一种场景这里的impl-mStrong就必然等于0而不会等于INITIAL_STRONG_VALUE值因此这里就不需要delete目标对象了(impl-mBase)因为前面的RefBase::decStrong函数会负责delete这个对象。这里唯一需要做的就是把weakref_impl对象delete掉但是为什么要在这里delete这个weakref_impl对象呢这里的weakref_impl对象是在RefBase的构造函数里面new出来的理论上说应该在在RefBase的析构函数里delete掉这个weakref_impl对象的。在RefBase的析构函数里面的确是会做这件事情RefBase::~RefBase(){// LOGV(Destroying RefBase %p (refs %p)\n, this, mRefs);if (mRefs-mWeak 0) {// LOGV(Freeing refs %p of old RefBase %p\n, mRefs, this);deletemRefs;}}但是不要忘记在这个场景下目标对象是前面的RefBase::decStrong函数delete掉的这时候目标对象就会被析构但是它的弱引用计数值尚未执行减1操作因此这里的mRefs-mWeak 0条件就不成立于是就不会delete这个weakref_impl对象因此就延迟到执行这里decWeak函数时再执行。如果是后一种情景这里的impl-mStrong值就等于INITIAL_STRONG_VALUE了这时候由于没有地方会负责delete目标对象因此就需要把目标对象(imp-mBase)delete掉了否则就会造成内存泄漏。在delete这个目标对象的时候就会执行RefBase类的析构函数这时候目标对象的弱引用计数等于0于是就会把weakref_impl对象也一起delete掉了。