什么是编程时的资源
资源就是哪些一旦使用了将来必须归还给系统的东西。比如内存、文件句柄、互斥锁、数据库连接以及网络socket等。
这里以内存管理为例。
内存管理可能出现的问题
- 使用已被delete的内存
- 没有delete释放内存
- 对同一块内存delete两次
什么时候需要动态分配内存
当我们需要共享同一个资源( shared_ptr) 或 独占一个资源 (unique_ptr) 时。
对于这样的需求,不建议使用动态内存分配:
int Size = 105;
int* p = new int[Size];
更合适的方法是:
vector<int> vec;
//vector可以高速增长,或者说push_back的速度非常快
不建议动态分配数组内存
因为vector与string的存在,C++对内存的需求可以降为零。
此外,对数组的释放使用delete[] ,对单独资源的释放使用delete,二者的底层逻辑还不一样( delete[]在内存组织时有一个记录空间的大小的常量,然后连续调用delete),动态分配数组容易出错。
以对象管理资源
- 获得资源后立即放进负责资源管理的对象内: RAII( Resource Acquisition Is Initialization)
- 管理对象在析构时确保其管理的资源正确释放: C++对象的作用域离开析构函数时会自动调用析构函数,在这里完成管理资源的释放。
shared_ptr的使用
头文件:
#include<memory>
构造:
//shared_ptr的构造是explicit的
shared_ptr<int> p(new int);
//shared_ptr还允许用户自定义删除器
class Deleter{
public:
void operator()(int* p){
cout << "called" << endl;
delete p;
}
};
大小:经过测试,智能指针的大小是为未封装指针大小的两倍
使用方法:与未封装指针一样
常用函数:
函数 | 功能 |
---|---|
get | 返回未封装的指针(常用于接口的转换) |
reset | 更改指针指向的位置 |
make_shared | 返回智能指针,常用于初始化 |
use_count | 查看引用次数 |
举例:Mutex资源的管理
C++中内置了两个C的API,这两个API并没有进行资源管理,因此需要自己创建资源管理类。
void lock(Mutex* pm);
void unlock(Mutex* pm);
class Lock{
public:
explicit Lock(Mutex* pm) : mutexPtr(pm, unlock)
{
lock(mutexPtr.get());
}
private:
shared_ptr<Mutex> mutexPtr;
}
资源管理类对copy的处理
- 计数器法(浅拷贝):对一块资源的引用计数,计数器为0时释放资源。(shared_ptr)
- 禁止复制:像cin、cout这样的对象以及互斥器对象等,不能进行赋值。(unique_ptr)
- 深拷贝:复制底层资源,这种情况下需要自己写资源管理类。