1. 资源
1.1 系统中的资源
- 内存
- 文件描述符
- Socket套接字
- 内核同步/互斥资源(Mutex)
1.2 资源“泄露“
由于系统中的资源有限,所以在需要的时候去申请,在不需要的时候应该立即释放。但是由于程序提前结束或者误操作很容易忘记对资源的释放。这就会造成资源的“泄露”,如常见的“内存泄露“和“死锁”。
内存泄漏
Object* p = new Object();
doSomething();
delete p;
如果在调用doSomething
的过程中捕获到异常导致直接返回或者忘记执行delete
操作,那么p
指向的内存就没有释放,导致内存泄露。
死锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex);
doSomething();
pthread_mutex_unlock(&mutex);
如果忘记unlock
被锁住的mutex
或者在doSomething
的过程中直接返回,那么mutex
将一直被锁住,其他等待该mutex
的线程将一直阻塞。
2. RAII
RAII(Resource Acquisition Is Initialization),直译为“资源获取即初始化”。从名字中不能很好的体会其本质,其本质为使用对象对资源进行管理(主要资源的释放)。
2.1 局部对象
在C++中,局部对象的是存储在栈空间上,只在一定的作用域内有效,但控制将要离开作用域时,操作系统自动析构局部对象,并将占用的资源回收。
2.2 利用局部对象管理资源
正如上面提到,我们可以利用局部对象能被自动析构/释放这一特性,将资源的生命周期和局部对象的生命周期绑定,这样就间接的借由操作系统来管理资源。
具体做法如下:
- 局部对象含有资源的一个指针
p
- 在局部对象的构造函数中使
P
指向已申请的资源; - 在局部对象的函数中
delete p
3. 使用RAII对Mutex的一个简单封装
#include <pthread.h>
class Mutex
{
public:
Mutex()
{
pthread_mutex_init(m_mutex);
}
~Mutex()
{
pthread_mutex_destory(m_mutex)
}
private:
pthread_mutex_t m_mutex;
Mutex(Mutex&){}
Mutex& operator=(Mutext&){}
friend class MutexLock;
};
class MutexLock
{
public:
MutexLock(Mutex& mutex):m_mutex(&mutex.m_mutex)
{
pthread_mutex_lock(m_mutex);
}
~Mutexlock()
{
pthread_mutex_unlock(m_mutex);
}
private:
pthread_mutex_t* m_mutex;
MutexLock(MutexLock&){}
MutexLock& operator=(MutexLock&){}
};
4. C++智能指针
除了使用自己实现的资源管理对象对资源进行管理外,在C++11
中可以使用STL
提供的智能指针
对资源进行管理
在STL
中有三种智能指针
1. std::shared_ptr
2. std::unique_ptr
3. std::weak_ptr