RAII
RAII(Resource Acquisition Is Initialization)翻译过来就是资源获取即初始化,更准确的表达是使用对象来管理资源。
单纯依靠new和delete的期望执行是行不通的,甚至有时会有隐藏new的资源(比如函数返回的资源)。因此我们寄希望于析构函数自动调用的机制来确保资源释放。对于局部作用域内的资源,可以使用栈对象来管理,而对于堆上的资源,可以使用智能指针来管理。不要将资源的申请和释放分开进行,这样可以避免手动释放资源的麻烦,也可以避免忘记释放资源的错误。
以对象管理资源的关键步骤:
- 获得资源后立刻放入管理对象,因此叫做RAII
- 管理对象运行析构函数确保释放资源
以下是一些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
a -----> B
b -----> A
A->bPtr -----> B
B->aPtr -----> A
AB互指成环
*/