C++程序最常使用的资源便是动态内在分配,其他常见资源包括文件描述符、互斥锁、图形界面的字型和笔刷、数据库连接、网络socket,不论哪种资源,不再使用时都需要还给系统。
资源管理的好办法是基于对象管理,建立在C++构造函数、析构函数、copying函数上,严守以下方法几乎可消除资源管理问题。
条款13:Use objects to manage resources.以对象管理资源
控制流中资源使用完成后释放资源,但当控制流语句抛出异常或其他原因来不及调用释放语句时,造成资源泄漏,谨慎的编写程序可防止此类错误,但多人共同开发代码或后期维护会造成与本意相违的执行,或是异常抛出,因此单纯依赖控制流一定会执行释放语句不可靠。
为确保资源一定会被释放,将资源放进对象内,控制流离开对象作用域时对象析构函数自动释放资源。把资源放进对象内,依赖C++析构函数自动调用机制确保资源释放。获得资源后立刻放进管理对象内,管理对象运用析构函数确保资源释放。
标准库提供智能指针管理动态对象,自动释放所指向的对象。
条款14:Think carefully about copying behavior in resource-managing classes.在资源管理类中小心copying行为
条款13中资源取得时机便是初始化时机(RAII),当建立自己的资源管理类时,需要注意RAII对象复制问题,一般是禁止复制或底层资源引用计数。标准库提供的智能指针便是使用底层引用计数,当引用计数为0时删除其所指物。假设智能指针管理对象为互斥锁,当锁的引用计数为0时需要解除锁定而不是删除,此时可指定智能指针的删除器为解锁操作。
复制底层资源时需要深度拷贝,或者转移底部资源的拥有权。Copying函数除非编绎器合成版本与预期行为一致否则需要自行定义。资源的copying行为决定了RAII对象的copying行为,常见的RAII class copying行为是:抑制copying、引用计数。
条款15:Provide access to raw resources in resource-managing classes.在资源管理类中提供原始资源的访问。
标准库智能指针提供get成员函数,返回智能指针内部的原始指针。
自定义资源管理类可提供隐式类型转换operator type() const。此类型转换运算符是隐式执行的,为避免隐式转换带来问题,C++11引入显式类型转换运算符,与显式构造函数一样,使用explicit关键字定义显式的类型转换,使用static_cast显式请求强制转换。
条款16:Use the same form in corresponding uses of new and delete.成对使用new和delete时要采取相同形式
当使用new时一分配内存,二调用构造函数,当使用delete时一调用析构函数,二释放内存。需要分配多少内存及删除多少对象,delete时删除的是单一对象还是对数数组,如果new时使用了[],delete时也必须使用[],如果调用时没有使用[],delete时不可使用[]。
条款17:Store newed objects in smart pointers in standalone statements.以独立语句将newed对象置入智能指针
若资源创建及资源管理等其他操作在同一语句,编绎器可任意决定执行次序,在资源创建及资源转换为资源管理对象之间发生异常干扰,则会导致创建的资源未被管理而导致泄漏。但编绎器对跨越语句的操作不得任意决定执行次序,所以需求以独立语句将new出的对象存储于智能指针。



