C++ 智能指针

来源:互联网 发布:澳洲上市公司数据查询 编辑:程序博客网 时间:2024/06/11 04:08

本文参考http://blog.csdn.net/luoshengyang/article/details/6786239

一、RefBash.h

class RefBase{public:        void            incStrong(const void* id) const;        void            decStrong(const void* id) const;        int             getStrongCount() const;    class weakref_type    {    public:RefBase*            refBase() const;void                incWeak(const void* id);void                decWeak(const void* id);bool                attemptIncStrong(const void* id);int                 getWeakCount() const;    };        weakref_type*   createWeak(const void* id) const;        weakref_type*   getWeakRefs() const;protected:                        RefBase();    virtual                 ~RefBase();//delete this时候会调用子类    enum {OBJECT_LIFETIME_WEAK    = 0x0001,OBJECT_LIFETIME_FOREVER = 0x0003    };            void            extendObjectLifetime(int  mode);    enum {FIRST_INC_STRONG = 0x0001    };    virtual bool            onIncStrongAttempted(int flags, const void* id);//子类可以覆盖private:    //friend class weakref_type;    class weakref_impl; //不能include,只能前向声明        RefBase(const RefBase& o);        RefBase&    operator=(const RefBase& o);        weakref_impl* const mRefs;};// ---------------------------------------------------------------------------template <typename T>class sp{public:typedef typename RefBase::weakref_type weakref_type;//相当于typedef  RefBase::weakref_type weakref_typ    sp(T* other);    sp(const sp<T>& other);    ~sp();    inline  T*      get() const         { return m_ptr; }private:    template<typename Y> friend class wp;//wp可以操作sp的私有变量,如构造函数     sp(T* p, weakref_type* refs);    T*              m_ptr;};// ---------------------------------------------------------------------------template <typename T>class wp{public:typedef  RefBase::weakref_type weakref_type;    wp(T* other);    wp(const wp<T>& other);    ~wp();    sp<T> promote() const;    inline  weakref_type* get_refs() const { return m_refs; }private:    T*              m_ptr;//strongPointer    weakref_type*   m_refs;//weakref_impl};// ---------------------------------------------------------------------------template<typename T>sp<T>::sp(T* other)    : m_ptr(other)//strongPointer{    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>sp<T>::~sp(){    if (m_ptr) m_ptr->decStrong(this);}template<typename T>sp<T>::sp(T* p, weakref_type* refs)    : m_ptr((p && refs->attemptIncStrong(this)) ? p : 0){}// ---------------------------------------------------------------------------template<typename T>wp<T>::wp(T* other)    : m_ptr(other)//strongPointer{    if (other) m_refs = other->createWeak(this);//weakref_impl}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);}template<typename T>wp<T>::~wp(){    if (m_ptr) m_refs->decWeak(this);}template<typename T>sp<T> wp<T>::promote() const{    return sp<T>(m_ptr, m_refs);}


二、RefBase.cpp

#include "RefBase.h"#include <iostream>using namespace std;#define INITIAL_STRONG_VALUE (1<<28)class RefBase::weakref_impl : public RefBase::weakref_type{public:    volatile int    mStrong;    volatile int    mWeak;    RefBase* const      mBase;    volatile int    mFlags;    weakref_impl(RefBase* base)        : mStrong(INITIAL_STRONG_VALUE)        , mWeak(0)        , mBase(base)        , mFlags(0)    {    }    ~weakref_impl()    {    cout << "~weakref_impl"<<endl;    }};// ---------------------------------------------------------------------------void RefBase::incStrong(const void* id) const{    weakref_impl* const refs = mRefs;    refs->incWeak(id);    const int c = refs->mStrong++;    if (c != INITIAL_STRONG_VALUE)  {        return;    }    refs->mStrong = refs->mStrong - INITIAL_STRONG_VALUE;}void RefBase::decStrong(const void* id) const{    weakref_impl* const refs = mRefs;    const int c = --refs->mStrong;    if (c == 0) {        if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//受到强指针控制            delete this;        }    }    refs->decWeak(id);}int RefBase::getStrongCount() const{    return mRefs->mStrong;}RefBase* RefBase::weakref_type::refBase() const{    return static_cast<const weakref_impl*>(this)->mBase;}void RefBase::weakref_type::incWeak(const void* id){    weakref_impl* const impl = static_cast<weakref_impl*>(this);    impl->mWeak++;}void RefBase::weakref_type::decWeak(const void* id){    weakref_impl* const impl = static_cast<weakref_impl*>(this);    const int c = --impl->mWeak;    if (c != 0) return;    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//受强指针控制        if (impl->mStrong == INITIAL_STRONG_VALUE){            delete impl->mBase;        }        else {            delete impl;        }    } else {        if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {//受弱指针控制            delete impl->mBase;        }    }}bool RefBase::weakref_type::attemptIncStrong(const void* id){    incWeak(id);//先增加,后面有减少,整体不变    weakref_impl* const impl = static_cast<weakref_impl*>(this);    int curCount = impl->mStrong;    if (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {//mStrong变化过,且大于0    impl->mStrong = curCount + 1;        curCount = impl->mStrong;    }    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {//mStrong没有变化过;或者变化后,为0        bool allow;        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) {            decWeak(id);//再减少            return false;        }        curCount = impl->mStrong++;    }    if (curCount == INITIAL_STRONG_VALUE) {impl->mStrong = impl->mStrong - INITIAL_STRONG_VALUE;    }    return true;}int RefBase::weakref_type::getWeakCount() const{    return static_cast<const weakref_impl*>(this)->mWeak;}RefBase::weakref_type* RefBase::createWeak(const void* id) const{    mRefs->incWeak(id);    return mRefs;}RefBase::weakref_type* RefBase::getWeakRefs() const{    return mRefs;}RefBase::RefBase()    : mRefs(new weakref_impl(this)){}RefBase::~RefBase(){    if (mRefs->mWeak == 0) {        delete mRefs;    }}void RefBase::extendObjectLifetime(int mode){    mRefs->mFlags = mode;}bool RefBase::onIncStrongAttempted(int flags, const void* id){    return (flags&FIRST_INC_STRONG) ? true : false;}


void RefBase::decStrong(const void* id) const{    weakref_impl* const refs = mRefs;    const int c = --refs->mStrong;    if (c == 0) {        if ((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//受到强指针控制            delete this;        }    }    refs->decWeak(id);}
减少强引用计数时候,同时减少弱引用计数,如果强引用计数为0,并且受强指针控制,那么调用子类和RefBase的析构函数


void RefBase::weakref_type::decWeak(const void* id){    weakref_impl* const impl = static_cast<weakref_impl*>(this);    const int c = --impl->mWeak;    if (c != 0) return;    if ((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {//受强指针控制        if (impl->mStrong == INITIAL_STRONG_VALUE){            delete impl->mBase;        }        else {            delete impl;        }    } else {        if ((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {//受弱指针控制            delete impl->mBase;        }    }}


RefBase::~RefBase(){    if (mRefs->mWeak == 0) {        delete mRefs;    }}

减少弱引用计数,如果弱引用计数为0,并且受弱指针控制,那么调用delete impl->mBase,调用上面的析构函数,因为此时mWeek==0,所以执行delete mRefs

如果弱引用计数为0,并且不受强指针,也不受弱指针控制,那么由自己调用delete来删除

如果弱引用计数为0,并且受强指针控制,如果强引用计数为0,那么只delete impl,因为RefBase及其子类已经被delelte掉了

如果弱引用计数为0,并且受强指针控制,如果强引用计数为INITIAL_STRONG_VALUE,那么说明RefBase及其子类还没有删除,那么要delelte impl->mBase,调用上面的析构函数,因为此时mWeek==0,所以执行delete mRefs


bool RefBase::weakref_type::attemptIncStrong(const void* id){    incWeak(id);    weakref_impl* const impl = static_cast<weakref_impl*>(this);    int curCount = impl->mStrong;    if (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {    impl->mStrong = curCount + 1;        curCount = impl->mStrong;    }    if (curCount <= 0 || curCount == INITIAL_STRONG_VALUE) {        bool allow;        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) {            decWeak(id);            return false;        }        curCount = impl->mStrong++;    }    if (curCount == INITIAL_STRONG_VALUE + 1) {impl->mStrong = impl->mStrong - INITIAL_STRONG_VALUE;    }    return true;}

    if (curCount > 0 && curCount != INITIAL_STRONG_VALUE) {    impl->mStrong = curCount + 1;        curCount = impl->mStrong;    }

如果此时强引用计数不为0,或者初始值,那么说明RefBase及其子类还没有删除,所以可以提升为强引用



            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) == OBJECT_LIFETIME_WEAK                  && impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);

如果此时强引用计数为0,并且还受强指针控制,那么此时,RefBase及其子类已经被删除了,所以不能提升为强引用

如果此时强引用计数为0,并且还受弱指针控制,那么此时,RefBase及其子类还没有删除,能不能提升就看impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)的了


            allow = (impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK                  || impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id);

如果此时强引用计数为INITIAL_STRONG_VALUE,并且还受强指针控制,此时RefBase及其子类还没有删除,所以能够提升。

如果此时强引用计数INITIAL_STRONG_VALUE,并且还受弱指针控制,此时RefBase及其子类还没有删除,能不能提升就看impl->mBase->onIncStrongAttempted(FIRST_INC_STRONG, id)的了


三、main.cpp

#include <stdio.h>#include "RefBase.h"#define INITIAL_STRONG_VALUE (1<<28)class WeightClass: public RefBase {public:void printRefCount() {int strong = getStrongCount();weakref_type* ref = getWeakRefs();printf("-----------------------\n");printf("Strong Ref Count: %d.\n",(strong == INITIAL_STRONG_VALUE ? 0 : strong));printf("Weak Ref Count: %d.\n", ref->getWeakCount());printf("-----------------------\n");}};class StrongClass: public WeightClass {public:StrongClass() {printf("Construct StrongClass Object.\n");}virtual ~StrongClass() {printf("Destory StrongClass Object.\n");}};class WeakClass: public WeightClass {public:WeakClass() {extendObjectLifetime(OBJECT_LIFETIME_WEAK);printf("Construct WeakClass Object.\n");}virtual ~WeakClass() {printf("Destory WeakClass Object.\n");}};class ForeverClass: public WeightClass {public:ForeverClass() {extendObjectLifetime(OBJECT_LIFETIME_FOREVER);printf("Construct ForeverClass Object.\n");}virtual ~ForeverClass() {printf("Destory ForeverClass Object.\n");}};void TestStrongClass(StrongClass* pStrongClass) {wp<StrongClass> wpOut = pStrongClass;pStrongClass->printRefCount();{sp<StrongClass> spInner = pStrongClass;pStrongClass->printRefCount();}pStrongClass->printRefCount();sp<StrongClass> spOut = wpOut.promote();printf("spOut: %p.\n", spOut.get());pStrongClass->printRefCount();}void TestStrongClass2(StrongClass* pStrongClass) {wp<StrongClass> wpOut = pStrongClass;pStrongClass->printRefCount();}void TestStrongClass4(StrongClass* pStrongClass) {wp<StrongClass> wpOut = pStrongClass;pStrongClass->printRefCount();sp<StrongClass> spInner = pStrongClass;pStrongClass->printRefCount();sp<StrongClass> spOut = wpOut.promote();printf("spOut: %p.\n", spOut.get());pStrongClass->printRefCount();}void TestStrongClass3(StrongClass* pStrongClass) {wp<StrongClass> wpOut = pStrongClass;pStrongClass->printRefCount();sp<StrongClass> spOut = wpOut.promote();printf("spOut: %p.\n", spOut.get());pStrongClass->printRefCount();}void TestWeakClass(WeakClass* pWeakClass) {wp<WeakClass> wpOut = pWeakClass;pWeakClass->printRefCount();{sp<WeakClass> spInner = pWeakClass;pWeakClass->printRefCount();}pWeakClass->printRefCount();sp<WeakClass> spOut = wpOut.promote();printf("spOut: %p.\n", spOut.get());pWeakClass->printRefCount();}void TestForeverClass(ForeverClass* pForeverClass) {wp<ForeverClass> wpOut = pForeverClass;pForeverClass->printRefCount();{sp<ForeverClass> spInner = pForeverClass;pForeverClass->printRefCount();}pForeverClass->printRefCount();}int main(int argc, char** argv) {/*    printf("Test Strong Class: \n"); StrongClass* pStrongClass = new StrongClass(); TestStrongClass(pStrongClass);*//*        printf("Test Strong Class2: \n"); StrongClass* pStrongClass = new StrongClass(); TestStrongClass2(pStrongClass);*//*        printf("\nTest Weak Class: \n"); WeakClass* pWeakClass = new WeakClass(); TestWeakClass(pWeakClass);*//*        printf("\nTest Froever Class: \n"); ForeverClass* pForeverClass = new ForeverClass(); TestForeverClass(pForeverClass); pForeverClass->printRefCount(); delete pForeverClass;*//* printf("Test Strong Class3: \n"); StrongClass* pStrongClass = new StrongClass(); TestStrongClass3(pStrongClass);*/printf("Test Strong Class4: \n");StrongClass* pStrongClass = new StrongClass();TestStrongClass4(pStrongClass);return 0;}


四、运行结果

第一个:

Test Strong Class: 
Construct StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: (nil).
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
~weakref_impl

第二个:

Test Strong Class2: 
Construct StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
Destory StrongClass Object.
~weakref_impl


第三个:

Test Weak Class: 
Construct WeakClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: 0x1d60010.
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory WeakClass Object.
~weakref_impl


第四个:

Test Froever Class: 
Construct ForeverClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 0.
-----------------------
Destory ForeverClass Object.
~weakref_impl


第五个:

Test Strong Class3: 
Construct StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
spOut: 0x646010.
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
Destory StrongClass Object.
~weakref_impl


第六个:

Test Strong Class4: 
Construct StrongClass Object.
-----------------------
Strong Ref Count: 0.
Weak Ref Count: 1.
-----------------------
-----------------------
Strong Ref Count: 1.
Weak Ref Count: 2.
-----------------------
spOut: 0x154e010.
-----------------------
Strong Ref Count: 2.
Weak Ref Count: 3.
-----------------------
Destory StrongClass Object.
~weakref_impl



2 2
原创粉丝点击