【C++】RAII:资源获取即初始化


RAII:资源获取即初始化

什么是RAII?

RAII,全称为Resource Acquisition Is Initialization,由C++之父Bjarne Stroustrup提出,中文翻译为“资源获取即初始化”。Stroustrup说:“使用局部对象来管理资源的技术称为资源获取即初始化。” 这里的资源主要是指操作系统中的有限资源,如内存、网络套接字等。局部对象是指存储在栈上的对象,其生命周期由操作系统管理,无需人工介入。

RAII的原理

资源的使用一般经历以下三个步骤:

  1. 获取资源
  2. 使用资源
  3. 销毁资源

然而,资源的销毁常常是程序员容易忽略的一个环节。为了让资源自动销毁,Bjarne Stroustrup提出了RAII方案。它充分利用了C++语言中局部对象自动销毁的特性来控制资源的生命周期。

下面我们通过一个简单的例子来看一下局部对象的自动销毁特性:

#include <iostream>
using namespace std;

class person {
public:
    person(const std::string name = "", int age = 0) : 
    name_(name), age_(age) {
        std::cout << "Init a person!" << std::endl;
    }
    ~person() {
        std::cout << "Destroy a person!" << std::endl;
    }
    const std::string& getname() const {
        return this->name_;
    }    
    int getage() const {
        return this->age_;
    }      
private:
    const std::string name_;
    int age_;  
};

int main() {
    person p;
    return 0;
}

编译并运行:

g++ person.cpp -o person
./person

运行结果:

Init a person!
Destroy a person!

person类可以看出,当我们在main函数中声明一个局部对象时,会自动调用构造函数进行对象的初始化。当main函数执行完成后,自动调用析构函数来销毁对象。整个过程无需人工介入,由操作系统自动完成。因此,在使用资源时,我们可以在构造函数中进行初始化,在析构函数中进行销毁。

RAII的步骤

RAII过程可以总结为以下四个步骤:

  1. 设计一个类封装资源。
  2. 在构造函数中初始化资源。
  3. 在析构函数中销毁资源。
  4. 使用时声明一个该类的对象。

RAII的应用

为了更好地理解RAII的应用,我们通过一个简单的例子来说明如何将RAII应用到实际代码中。在Linux下,经常会使用多线程技术,而多线程中不可避免地会用到互斥锁。互斥锁用于保护临界资源,使其一次只被一个线程访问。我们可以封装POSIX标准的互斥锁来实现RAII。

#include <pthread.h>
#include <iostream>

class Mutex {
public:
    Mutex() {
        pthread_mutex_init(&mutex_, nullptr);
    }
    ~Mutex() {
        pthread_mutex_destroy(&mutex_);
    }
    void lock() {
        pthread_mutex_lock(&mutex_);
    }
    void unlock() {
        pthread_mutex_unlock(&mutex_);
    }
private:
    pthread_mutex_t mutex_;
};

class LockGuard {
public:
    LockGuard(Mutex& mutex) : mutex_(mutex) {
        mutex_.lock();
    }
    ~LockGuard() {
        mutex_.unlock();
    }
private:
    Mutex& mutex_;
};

void* threadFunc(void* arg) {
    Mutex* mutex = static_cast<Mutex*>(arg);
    LockGuard lock(*mutex);
    // 在此处使用临界资源
    std::cout << "Thread is running..." << std::endl;
    return nullptr;
}

int main() {
    Mutex mutex;
    pthread_t thread;
    pthread_create(&thread, nullptr, threadFunc, &mutex);
    pthread_join(thread, nullptr);
    return 0;
}

在这个例子中,Mutex类封装了互斥锁的初始化和销毁,LockGuard类则利用RAII技术在构造函数中锁定互斥锁,并在析构函数中解锁。这确保了互斥锁在任何情况下都能被正确解锁,而无需手动干预。

总结

RAII是一种强大的资源管理技术,通过在对象的生命周期中自动管理资源的获取和释放,提高了代码的安全性和可维护性。通过封装资源、在构造函数中初始化、在析构函数中销毁,我们可以确保资源在正确的时间点被释放,从而减少资源泄漏和其他潜在问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SuhyOvO

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

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

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

打赏作者

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

抵扣说明:

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

余额充值