RAII

发布时间 2023-10-18 23:10:45作者: cerwang

RAII(Resource Acquisition Is Initialization)翻译过来就是资源获取即初始化,更准确的表达是使用对象来管理资源。
单纯依靠new和delete的期望执行是行不通的,甚至有时会有隐藏new的资源(比如函数返回的资源)。因此我们寄希望于析构函数自动调用的机制来确保资源释放。对于局部作用域内的资源,可以使用栈对象来管理,而对于堆上的资源,可以使用智能指针来管理。不要将资源的申请和释放分开进行,这样可以避免手动释放资源的麻烦,也可以避免忘记释放资源的错误。
以对象管理资源的关键步骤:

  1. 获得资源后立刻放入管理对象,因此叫做RAII
  2. 管理对象运行析构函数确保释放资源

以下是一些RAII的例子
范围互斥锁,在进入作用域内时获得锁,离开作用域时释放锁

class MutexLock {
public:
    MutexLock(pthread_mutex_t* mutex_t):mutex(mutex_t) {
        lock();
    }
    ~MutexLock() {
        unlock();
    }
    void lock() {
        pthread_mutex_lock(mutex);
    }
    void unlock() {
        pthread_mutex_unlock(mutex);
    }
private:
    pthread_mutex_t* mutex;
};

智能指针就是RAII的一个例子
shared_ptr在引用计数为0时自动释放资源,但无法破除环状引用

一个例子

#include<memory>
#include<iostream>
using namespace std;
class B;
int cnt=0;
class A {
public:
    std::shared_ptr<B> bPtr;
    ~A(){
        cout<<cnt--<<" ";
        cout<<"A is deleted"<<endl;
    }
    A(){
        cnt++;
        cout<<"A is created"<<endl;
    }
};

class B {
public:
    std::shared_ptr<A> aPtr;
    ~B(){
        cout<<cnt--<<" ";
        cout<<"B is deleted"<<endl;
    }
    B(){
        cnt++;
        cout<<"B is created"<<endl;
    }
};

int main() {
    // circle
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();

    a->bPtr = b;
    b->aPtr = a;

    cout<<a.get()<<endl;
    cout<<b.get()<<endl;
    cout<<a->bPtr.get()<<endl;
    cout<<b->aPtr.get()<<endl;
    return 0;
}

/*
A is created
B is created
0x1031770
0x1031ae0
0x1031ae0
0x1031770
*/

image