首页 > 编程语言 > 详细

Effective C++ 条款08:别让异常逃离析构函数

时间:2021-06-30 21:07:52      阅读:17      评论:0      收藏:0      [点我收藏+]

析构函数抛出异常会有什么后果

假设现在我们有一个类Widget

class Widget{
public:
    ...;
    ~Widget() {
        // 这里抛出异常了
        ...;
    }
};

然后我们创建一个Widget类型的的vector数组

int main(){
    std::vector<Widget> v;
}

假设现在v的生命周期结束了,它会析构掉里面的所有Widget对象

然而此时,析构第一个Widget对象时抛出了异常。为了防止内存泄露,我们依然要保证后面的其他所有Widget对象被析构。

但很不幸的是,析构第二个Widget时又抛出了一个异常。那么此时编译器抛出了两个异常。对于c++而言抛出两个异常是非常危险的,这会导致程序执行不明确行为。具体为什么在More Effective里有讲到,这里只需知道c++不喜欢析构函数抛出异常即可

但是析构函数必须执行一个可能抛出异常的动作怎么办

书上告诉我们:交给用户

考虑这个数据库管理类

class DBConnection;
class DBConn{
public:  
    ~DBConn(){
        db.close();
    }
private:
    DBConnection db;
};

DBConnection是一个数据库连接类,它有一个close方法,这个方法会抛出异常。我们希望设计一个新的类DBConn来管理数据库的连接与释放。也就是当DBConn对象析构时,自动关闭数据库连接。

但是很遗憾close这个方法会抛出异常。那么我们需要重新设计接口,提供一个普通函数(非析构)给用户,然他自己释放。如果用户也忘了,那才交给析构函数释放。如果这时候还出问题了,那就听天由命吧。不是所有的问题都有完美的解决方法的!

class DBConn{
public:
    // 给用户提供的普通函数来关闭连接
    void close(){
        db.close();
        closed = true;
    }
    ~DBConn(){
        if (!closed) { 	// 如果用户也忘了,就让析构函数来
            try{
                db.close();
            }
            catch (...) {	// 很不幸析构时抛出了异常
                // 要么记录下来,结束程序 std::abort()
                // 要么吞掉
            }
        }
    }
private:
    DBConnection db;
    bool closed;
}

Effective C++ 条款08:别让异常逃离析构函数

原文:https://www.cnblogs.com/destinyzk/p/14955984.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!