RALL 与 智能指针


一、RALL是什么?

RALL是一种编程思想,对于一些重要资源(申请的空间,网络连接,互斥量等)我们需要在申请使用后将其释放掉,不然会造成资源的浪费。而RALL就是释放资源的一种方式,利用c++的特性,在构造函数中获取资源,析构函数中释放资源,利用对象控制资源的生存。

例子:

class sem
{
public:
    sem()
    {
        if (sem_init(&m_sem, 0, 0) != 0)
        {
            throw std::exception();
        }
    }
    sem(int num)
    {
        if (sem_init(&m_sem, 0, num) != 0)
        {
            throw std::exception();
        }
    }
    ~sem()
    {
        sem_destroy(&m_sem);
    }
    bool wait()
    {
        return sem_wait(&m_sem) == 0;
    }
    bool post()
    {
        return sem_post(&m_sem) == 0;
    }

private:
    sem_t m_sem;
};
class locker
{
public:
    locker()
    {
        if (pthread_mutex_init(&m_mutex, NULL) != 0)
        {
            throw std::exception();
        }
    }
    ~locker()
    {
        pthread_mutex_destroy(&m_mutex);
    }
    bool lock()
    {
        return pthread_mutex_lock(&m_mutex) == 0;
    }
    bool unlock()
    {
        return pthread_mutex_unlock(&m_mutex) == 0;
    }
    pthread_mutex_t *get()
    {
        return &m_mutex;
    }

private:
    pthread_mutex_t m_mutex;
};

二、智能指针

什么是智能指针?

利用RALL思想实现对申请空间的自动销毁,通过几个模板函数:unique_ptr,shared_ptr,auto_ptr,weak_ptr来实现。

(1)shared_ptr:

共享的智能指针,允许多个智能指针可以指向同一块资源,并且保证共享的资源只会被释放一次。

原理:内部维护了一个引用计数,当有指针引用空间时计数+1,析构时计数-1,当计数为0则释放资源。

实现:

这里将资源的管理和构造方法分开实现,实现智能指针需要,无参构造,构造函数,拷贝构造,移动构造,拷贝赋值,移动赋值,重构*和=。

代码如下(示例):


#pragma once
#include<iostream>
using namespace std;
template<class T>
class Ref
{
    
    int r_count = 0;//当前资源计数
    T* object = nullptr; //被管理的堆区内存
public:
    Ref(T *target) :object(target)
    {
        r_count++;
    }

    //引用计数加1
    inline void increase()
    {
        r_count++;
    }
    //引用计数减一并且判断是否要释放掉原始堆区内存
    inline void reduce()
    {
        r_count--;  //引用计数减一
        if (r_count == 0) //如果引用计数减为0释放被管理的堆区内存和自己
        {
            delete object;
            delete this;
        }
    }
    T *get()
    {
        return object;
    }
    int getCount()
    {
        return r_count;
    }
};
//共享智能指针需要的方法:
/*
        无参构造,传递指针构造,拷贝构造,移动构造,拷贝赋值,移动赋值
        reset()替换对象 reset()销毁对象
        operator*()  operator->()
        get()获取原始指针
        use_count 获得引用计数
*/
template<class T>
class Share_ptr
{
    Ref<T> * ref = nullptr;  //Ref使用模板,定义其指针时需加上模板参数<T>
public:
    Share_ptr() = default;
    ~Share_ptr()
    {
        if (ref) ref->reduce(); //引用计数减一
    }
    Share_ptr(T *newP)
    {
        cout << "---------------------调用构造函数-----------------" << endl;
        ref = new Ref<T>(newP);  //new申请空间同时调用构造函数,new申请无需指定空间大小()中的要走 前面类型的构造
    }
    Share_ptr(const Share_ptr &other)
    {
        cout << "------------------调用拷贝构造-----------------" << endl;
        this->ref = other.ref;
        if(ref) ref->increase(); //引用计数加1
    }
    Share_ptr( Share_ptr &&other)
    {
        cout << "------------------调用移动构造-----------------"<<endl;
        ref = other.ref;
        other.ref = nullptr;
    }
    Share_ptr& operator=(const Share_ptr &other)
    {
        cout << "-------------------------调用赋值函数-----------------------"<<endl;
        if (ref)
        {
            ref->reduce();
        }
        ref = other.ref;
        if (ref)
        {
            ref->increase();
        }
        return *this;
    }
    Share_ptr& operator =(Share_ptr &&other)
    {
        cout << "--------------------------调用移动赋值------------------------"<<endl;
        if (ref)
        {
            ref->reduce();
        }
        ref = other.ref;
        other.ref = nullptr;
        return *this;
    }
   
    T& operator*()
    {
        return *ref->get();
    }
    T* operator->()
    {
        if (ref)
        {  
            return ref->get();
        }
    }
    int use_count()
    {
        if (ref) return ref->getCount();
        else return 0;
    }
};

这里并没有考虑多线程问题,多线程中对引用计数操作需要加锁

注意:使用拷贝构造实则时复制,引用计数会增加,而移动构造不会,他是转让权限。

share_ptr初始化的方法:

1.构造函数初始化:

2.make_shared初始化:

(2)unique_ptr

该指针直接禁用了拷贝,赋值以及移动构造,是一个独占性指针。

总结

RALL是重要的编程思想,利用c++的特性实现自动管理资源,重要应用为智能指针,share_ptr等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BlackMonkeyHH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值