ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
再看第二个例子,代码如下所示: **例子2** ~~~ int main() { A *pA =new A(); wp<A> wpA(A); sp<A> spA = wpA.promote();//通过promote函数,得到一个sp。 } ~~~ 对A的wp化,不再做分析了。按照前面所学的知识,wp化后仅会使弱引用计数加1,所以此处wp化的结果是: - 影子对象的弱引用计数为1,强引用计数仍然是初始值0x1000000。 wpA的promote函数是从一个弱对象产生一个强对象的重要函数,试看: 1. 由弱生强的方法 代码如下所示: **RefBase.h** ~~~ template<typename T> sp<T> wp<T>::promote() const { returnsp<T>(m_ptr, m_refs); //调用sp的构造函数。 } ~~~ **RefBase.h** ~~~ template<typename T> sp<T>::sp(T* p, weakref_type* refs) :m_ptr((p && refs->attemptIncStrong(this)) ? p : 0)//有点看不清楚 { //上面那行代码够简洁,但是不方便阅读,我们写成下面这样: /* T* pTemp= NULL; //关键函数attemptIncStrong if(p !=NULL && refs->attemptIncStrong(this) == true) pTemp = p; m_ptr =pTemp; */ } ~~~ 2. 成败在此一举 由弱生强的关键函数是attemptIncStrong,它的代码如下所示: **RefBase.cpp** ~~~ boolRefBase::weakref_type::attemptIncStrong(const void* id) { incWeak(id);//增加弱引用计数,此时弱引用计数变为2 weakref_impl* const impl = static_cast<weakref_impl*>(this); int32_t curCount = impl->mStrong; //这个仍是初始值 //下面这个循环,在多线程操作同一个对象时可能会循环多次。这里可以不去管它, //它的目的就是使强引用计数增加1 while(curCount > 0 && curCount != INITIAL_STRONG_VALUE) { if(android_atomic_cmpxchg(curCount, curCount+1, &impl->mStrong) == 0) { break; } curCount = impl->mStrong; } if(curCount <= 0 || curCount == INITIAL_STRONG_VALUE) { bool allow; /* 下面这个allow的判断极为精妙。impl的mBase对象就是实际对象,有可能已经被delete了。 curCount为0,表示强引用计数肯定经历了INITIAL_STRONG_VALUE->1->...->0的过程。 mFlags就是根据标志来决定是否继续进行||或&&后的判断,因为这些判断都使用了mBase, 如不做这些判断,一旦mBase指向已经回收的地址,你就等着segment fault吧! 其实,咱们大可不必理会这些东西,因为它不影响我们的分析和理解。 */ if(curCount == INITIAL_STRONG_VALUE) { allow =(impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id); }else { allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) ==OBJECT_LIFETIME_WEAK && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG,id); } if(!allow) { //allow为false,表示不允许由弱生强,弱引用计数要减去1,这是因为咱们进来时加过一次 decWeak(id); return false; //由弱生强失败 } //允许由弱生强,则强引用计数要增加1,而弱引用计数已经增加过了 curCount = android_atomic_inc(&impl->mStrong); if(curCount > 0 && curCount < INITIAL_STRONG_VALUE) { impl->mBase->onLastStrongRef(id); } } impl->addWeakRef(id); impl->addStrongRef(id);//两个函数调用没有作用 if(curCount == INITIAL_STRONG_VALUE) { //强引用计数变为1 android_atomic_add(-INITIAL_STRONG_VALUE, &impl->mStrong); //调用onFirstRef,通知该对象第一次被强引用 impl->mBase->onFirstRef(); } returntrue; //由弱生强成功 } ~~~ 3. 第二板斧的结果 promote完成后,相当于增加了一个强引用。根据上面所学的知识可知: - 由弱生强成功后,强弱引用计数均增加1。所以现在影子对象的强引用计数为1,弱引用计数为2。