C++ RAII机制浅谈

一、RAII是什么?

        RAII全称为(Resource Acquisition Is Initialization),即“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。

        C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。利用这个特性就可以很好的管理创建好的资源。比如锁、信号、指针这类成套操作的资源,即有创建有销毁。

        个人理解:RAII机制或者RAII思想,简单的说,把需要创建的资源封装到类里面,在类的构造函数完成对资源的初始化,在类的析构函数中完成对资源的释放。

二、RAII的实现

先看一下忘记释放内存的结果是什么?

#include <iostream>

using namespace std;

int main()
{
    for(int i= 0;i< 10000000; i++)
    {
        int* data = new int[5];

        data[0] = i;
        data[1] = i;
        data[2] = i;
        data[3] = i;
        data[4] = i;

        //delete []data;
    }
    system("pause");
    return 0;
}

 可以看到,这个小程序的占用内存达到了300多M;下面是添加上delete的程序内存占用情况

所以在我们使用一些资源时忘记释放对于一些项目往往是很严重的,资源友好的释放也是c++程序员必备的素养。

利用RAII思想的代码实现如下:

使用模板类,能更好增加程序的可扩展性。

#ifndef RAII_TOOL_H
#define RAII_TOOL_H

template<class T>
class raII_tool
{
public:
    raII_tool(T *t):_t(t)
    {
        std::cout<<"raII_tool 构造函数被调用!"<<std::endl;
    }
    //析构函数完成资源的释放
    ~raII_tool()
    {
        std::cout<<"raII_tool 析构函数被调用!"<<std::endl;
        delete []_t;
    }
    //获取创建好的资源指针
    T * getPtr()
    {
        return _t;
    }

private:
    T *_t;
};

#endif // RAII_TOOL_H
#include <iostream>
#include "raII_tool.h"


int main()
{
    std::cout<<"main 函数执行!"<<std::endl;
    for(int i= 0;i< 1000000; i++)
    {
        auto raIITool = raII_tool<int>(new int[5]);
        int *data = raIITool.getPtr();

        data[0] = i;
        data[1] = i;
        data[2] = i;
        data[3] = i;
        data[4] = i;
    }

    std::cout<<"main 结束执行!"<<std::endl;
    system("pause");
    return 0;
}

结果如下:

 下面仔细的分析一下情况,这是调整循环次数为5,打印出的结果。

 raIITool这个对象的生命周期在大括号里面,每次调用raII_tool的构造函数,把new的内存地址传入构造函数并赋值给_t,在raIITool生命周期终止时调用析构函数,释放内存资源。RAII机制达到了自动释放资源的效果,与智能指针同理。

三、利用RAII思想封装sem信号

#ifndef SEM_H
#define SEM_H

#include <semaphore.h>

class sem
{
public:
    //构造函数初始化信号量
    sem()
    {
        if (sem_init(&m_sem, 0, 0) != 0)
        {
            throw std::exception();
        }
    }
    sem(int num)
    {
        std::cout<<"初始化信号"<<std::endl;
        if (sem_init(&m_sem, 0, num) != 0)
        {
            throw std::exception();
        }
    }
    //析构函数释放信号量
    ~sem()
    {
        std::cout<<"释放信号"<<std::endl;
        sem_destroy(&m_sem);
    }
    //sem_wait函数将以原子操作方式将信号量减一,信号量为0时,sem_wait阻塞
    bool wait()
    {
        return sem_wait(&m_sem) == 0;
    }
    //sem_post函数以原子操作方式将信号量加一,信号量大于0时,唤醒调用sem_post的线程
    bool post()
    {
        return sem_post(&m_sem) == 0;
    }

private:
    sem_t m_sem;
};
#endif // SEM_H

析构的时候就可以自动释放信号啦!

四、总结

        RAII机制使用远不止于此,上文只是简单的举一个小例子来说明RAII机制整体的一个思想,在真正的编程中,如果能够准确判断出内存释放的时机,可以直接选择delete掉内存。根据不同的环境选择不同的方法。

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值