EC++学习笔记(三) 资源管理
条款13:以对象管理资源
资源包括:动态分配内存、文件描述符、网络socket、互斥锁、数据库连接
把资源放进对象内,可以依赖c++的"析构函数自动调用机制"确保资源被释放
智能指针: 是一个"类指针"对象,引用计数型指针,当引用对象数为0时,自动删除该资源
std::shared_ptr<Class> pClass(new Class);
每一笔资源都在获得的同时立刻被放进管理对象中
条款14:在资源管理类小心copy行为
RAII:资源获取即初始化,资源在构造函数期间获得,析构函数期间释放
class Lock { public: explicit Lock(Mutex* pm) : mutexPtr(pm) { lock(mutexPtr); } ~Lock() { unlock(mutexPtr); } private: Mutex* mutexPtr; };
当一个RAII对象被复制时:
a.禁止复制:将copy函数声明为 private 且只声明不实现
b.引用计数:std::shared_ptr
shared_ptr 允许指定所谓的"删除器"(一个函数或函数对象),当引用计数为0时便被自动调用
class Lock{ public: explicit Lock(Mutex* pm) : mutexPtr(pm, unlock) { lock(mutexPtr.get()); } private: std::shared_ptr<Mutex> mutexPtr; };
c.复制底部资源,深度拷贝
d.慎用:auto_ptr,转移底部资源的拥有权,资源的拥有权会从被复制对象转移到目标对象
条款15:在资源管理类中提供对原始资源的访问
std::shared_ptr<Class> pClass(new Class);
现在某个函数要求访问原始资源:
int func(const Class *pClass);
如果我们调用:int result = func(pClass);
此时错误,因为func函数需要的是 Class* 指针(原始指针),而不是std::shared_ptr<Class>
shared_ptr提供一个get成员函数,用来执行显式转换,会返回智能指针内部的原始指针(的拷贝)
条款16:成对使用 new 和 delete 时要采用相同形式
如果 delete 加上中括号,delete 便认定指针指向一个数组,否则认定指针指向单一对象
string* stringPtr1 = new string; string* stringPtr2 = new string[100]; delete stringPtr1; //删除单一对象 delete []stringPtr2; //删除由对象组成的数组
条款17:以独立语句将newed对象置入智能指针
int func(std::shared_ptr<Widget> (new Widget), func1());
在调用func之前,编译器必须创建代码,做一下三件事:
1.调用func1()
2.执行 new Widget
3.调用shared_ptr的构造函数
c++编译器并未指定这3件事的执行次序
如果编译器按 2--->1--->3 的次序执行
当执行func1出现异常时, new Widget返回的指针并未成功置入 shared_ptr内,可能引发资源泄露
解决方法:以单独语句将newed对象置入智能指针内
std::shared_ptr<Widget> pw(new Widget); func(pw, func1());