weak pointer的实现方法


  1 #include  < assert.h >
  2 #include  < map >
  3 #include  < stdio.h >
  4
  5 //  memory leak checker
  6 struct  Value
  7 {
  8    bool valid;
  9    int line;
 10
 11    Value()
 12    :valid(false), line(-1)
 13    {}
 14
 15    Value(bool v, int l)
 16        :valid(v), line(l)
 17    {
 18    }

 19}
;
 20
 21 typedef std::map < void * , Value >  ContainerType;
 22 ContainerType myMap;
 23
 24 #define  mynew(x) mynew_(x, __LINE__)
 25
 26 void  checkMemory()
 27 {
 28    size_t n = myMap.size();
 29    //assert(n==0);
 30
 31    if(n>0)
 32    {
 33        printf("Memory leak found:\n");
 34        for (ContainerType::const_iterator it=myMap.begin();
 35            it!=myMap.end();++it)
 36        {
 37            printf("Line %d\n", it->second.line);
 38        }

 39        assert(0);
 40    }

 41}

 42
 43 template  < class  T >
 44 T *  mynew_(T  const   & n,  int  line)
 45 {
 46    T* p = (T*)malloc(sizeof(T));
 47    *= n;
 48    myMap[p]=Value(true, line);
 49    return p;
 50}

 51
 52 void  mydelete( void *  p)
 53 {
 54    ContainerType::iterator it = myMap.find(p);
 55    assert(it!=myMap.end());
 56    myMap.erase(it);
 57    free(p);
 58}

 59
 60 class  AutoPtr
 61 {
 62public:
 63    explicit AutoPtr(int *p=0)
 64    :p_(p), refCnt_(mynew(int(1))), valid_(mynew(bool(p?true:false)))
 65    {}
 66
 67    ~AutoPtr()
 68    {
 69        if(p_)
 70        {
 71            mydelete (p_);
 72        }

 73
 74        (*refCnt_)--;
 75        
 76        *valid_ = false;
 77
 78        assert(*refCnt_>=0);
 79        if(*refCnt_==0)
 80        {
 81            mydelete(refCnt_);
 82            mydelete(valid_);
 83        }

 84    }

 85
 86    bool empty() const
 87    {
 88        if(!*valid_) 
 89            assert(p_==0);
 90        else
 91            assert(p_!=0);
 92
 93        return !(*valid_);
 94    }

 95private:
 96    friend class WeakPtr;
 97    AutoPtr(const AutoPtr&);
 98    AutoPtr& operator =(const AutoPtr&);
 99
100    int *p_;
101    bool *valid_;
102    int *refCnt_;    //weak ref cnt, always valid if one weakPtr or AutoPtr exist
103}
;
104
105 class  WeakPtr
106 {
107public:
108    // ctor
109    WeakPtr()
110    :p_(0), refCnt_(mynew(int(1))), valid_(mynew(bool(false)))
111    {
112    }

113
114    explicit WeakPtr(AutoPtr& p)    //p must be valid
115    :p_(&p), refCnt_(p.refCnt_),valid_(p.valid_)
116    {
117        (*p_->refCnt_)++;
118    }

119    
120    WeakPtr(const WeakPtr& rhs)    //p must be valid
121    {
122        construct(rhs);
123    }

124
125    ~WeakPtr()
126    {
127        destroy();
128    }

129
130    // get
131    bool empty() const
132    {
133        assert((*refCnt_)>=0);
134        return !(*valid_);
135    }

136
137    // operator    
138    WeakPtr& operator=(const WeakPtr &rhs)
139    {
140        if(this!=&rhs)
141        {
142            destroy();
143            construct(rhs);
144        }

145        return *this;
146    }

147
148private:
149    void destroy()
150    {
151        (*refCnt_)--;
152
153        assert((*refCnt_)>=0);
154        if(0==*refCnt_)
155        {
156            mydelete(refCnt_);
157            mydelete(valid_);
158        }

159    
160    }

161    void construct(const WeakPtr &rhs)
162    {
163        p_ = rhs.p_;
164        refCnt_ = rhs.refCnt_;
165        valid_ = rhs.valid_;
166        (*refCnt_)++;
167    }

168
169    AutoPtr *p_;
170    bool *valid_;
171    int *refCnt_;    //weak ref cnt, always valid if one weakPtr or AutoPtr exist
172}
;
173
174 void  Test()
175 {
176    WeakPtr p1;
177
178    assert(p1.empty());
179    {
180        AutoPtr p(mynew(int(100)));
181        p1 = WeakPtr(p);
182        assert(!p1.empty());
183        assert(!p.empty());
184    }

185    assert(p1.empty());
186
187    //mynew(int());
188}

189
190 void  main()
191 {
192    Test();
193    checkMemory();
194}

你可能感兴趣的:(weak)