条款 08:别让异常逃离析构函数
Prevent exceptions from leaving destructors.
如果析构函数吐出异常,可能导致不明确行为,如下面 vector 销毁时会调用所有元素的析构函数,这会导致不明确行为
class A {...~A() {...} // 假设析构函数会吐出异常};void f() {std::vector<A> v;...}
关闭资源时经常会遇到类似问题,如处理数据库连接时为了方便做封装,就可能导致析构吐出异常
class DBConnection {public:static DBConnection create();void close();}class DBManager {public:...~DBManager() {db.close(); // 可能有异常逃离析构}private:DBConnection db;}{DBManager db(DBConnection::create());}
方法一:明确终止或吞掉异常
~DBManager() {try { db.close(); }catch (...) {log();std::abort(); // 明确终止}}~DBManager() {try { db.close(); }catch (...) {log(); // 直接吞掉异常}}
方法二:将析构函数中可能吐出异常的操作提取到普通函数,给用户自行处理异常的机会
class DBManager {public:...~DBManager() {if (!closed) {try {db.close();}catch (...) {log();}}}void close() // 由客户显式调用,自行处理异常{db.close();closed = true;}private:DBConnection db;bool closed;}
