【C++】动态内存管理(三)不同的资源管理对象的实现

这里我就直接贴代码然后进行说明了。

拷贝型资源管理对象

对于普适性的资源,比如string、vector、array等资源,我们通常采用拷贝的方式进行资源的赋值操作
下面是这种资源管理对象的基本构造:

    template<typename T>
    class Data
    {
    private:
        T* pointer;
    public:
        Data(const Data& d) :pointer(new T(*(d.pointer))) {};
        Data() :pointer(NULL) {};
        Data(T* p) :pointer(p)
        {

        };
        ~Data() 
        {
            delete pointer;
        }
        T& operator*() { return *(this->pointer); }
        Data& operator =(Data rhs)
        {
            delete pointer;
            pointer = new T(*(rhs.pointer)); 
            return *this;
        }
    };

然后我们测试一下:

    void test()
    {
        Data<int> p1(new int(3));
        Data<int>p2 = p1;
        *p2 = 5;
        cout << *p1 << " "<<*p2<<endl;//输出 3 5
    }

可以看到,当这种资源管理对象发生赋值的时候,就会产生新的资源副本,然后两个对象的资源就此隔离没有任何关系了。一个对象资源的改变不会影响另一个资源对象管理的资源

控制权转移的资源管理对象

这种控制权交换的情况有很多,比如mutex的锁等等临界资源,也就是只能被一个线程使用的资源,这样的资源不能进行拷贝,只能进行支配权的转移
大致构造如下:

    template<typename T>
    class Data
    {
    private:
        T* pointer;
    public:
        Data(Data& d):pointer( d.pointer)
        {
            d.pointer = NULL;
        };
        Data() :pointer(NULL) {};
        Data(T* p=NULL) :pointer(p)
        {

        };
        ~Data() 
        {
            delete pointer;
        }
        T& operator*() { return *(this->pointer); }
        Data& operator =(Data rhs)
        {
            delete pointer;
            pointer = rhs.pointer; 
            rhs.pointer = NULL;
            return *this;
        }
    };

当管理这种资源的对象进行赋值操作或则拷贝构造的时候,就会取消源资源对象对资源的的控制权,然后由新的资源管理对象对资源进行独自的管理

只有一个本体(但能被多个对象访问)的资源

还有一种资源,这种资源产生之后可以被大家共享。每个共享者实际上使用的都是同一个资源副本,当其中一个使用者被析构了不一定会释放内存,而是所有使用者都被销毁了,才会释放这块资源占据的内存。我们就添加一个计数器变量来统计使用者数量

下面就是一个简略的计数型资源管理对象的设计:

    template<typename T>
    class Data
    {
    private:
        size_t* count;
        T* pointer;
    public:
        Data(const Data& d) :pointer(d.pointer), count(d.count) 
        {
            ++(*count);
        }

        Data() :pointer(NULL),count(NULL) {};
        Data(T* p = NULL) :pointer(p), count(new size_t(1)) {};

        ~Data()
        {
            cout << "~Data" << endl;
            if (--(*count) == 0)
            {
                delete pointer;
                delete count;
                cout << "无人访问,删除共享资源" << endl;
            }
        }

        T& operator*() { return *(this->pointer); }
        size_t user() { return *count; };
        Data& operator =(Data rhs)
        {
            pointer = rhs.pointer; 
            count = rhs.count;
            *(this->count) += 1;
            return *this;
        }
    };

由于在赋值和拷贝的时候要对这个资源的所有计数器都进行更新,所以使用了size* count(一个指针对象)来进行实时同步。并且提供user()来查看当前有多少使用者。

一个测试代码:

void test()
    {
        Data<int> p1(new int(3));
        Data<int>p2 = p1;
        *p2 = 5;
        cout << *p1 << " " << *p2 << endl;
        cout << "user: " << p1.user() << endl;
    }

结果如下:

5 5
user: 2
~Data
~Data
无人访问,删除共享资源

可以看到,是很符合我们预期的,所有资源都可以很好的被分到不同的类别中去,然后进行不同类型资源的管理。保证资源的不同使用方法都能得到安全释放。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值