• weak pointer的实现方法



      1#include <assert.h>
      2#include <map>
      3#include <stdio.h>
      4
      5// memory leak checker
      6struct 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
     21typedef std::map<void*, Value> ContainerType;
     22ContainerType myMap;
     23
     24#define mynew(x) mynew_(x, __LINE__)
     25
     26void 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
     43template <class T>
     44T* 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
     52void 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
     60class 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
    105class 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
    174void 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
    190void main()
    191{
    192    Test();
    193    checkMemory();
    194}
  • 相关阅读:
    Revit API改变风管及管件尺寸
    Revit API注册事件
    Revit API创建标高,单位转换
    Revit API判断直线相交关系移动风管
    Revit MEP API找到连接器连接的连接器
    Revit MEP API连接器类别
    AngularJS如何编译和呈现页面
    AngularJS自定义Directive初体验
    Webpack基本用法
    对一个前端AngularJS,后端OData,ASP.NET Web API案例的理解
  • 原文地址:https://www.cnblogs.com/cutepig/p/1610915.html
Copyright © 2020-2023  润新知