EffectiveC++学习笔记-条款8

本文探讨了C++中析构函数如何正确处理资源释放,特别是当资源释放可能引发异常时的解决方案。提供了几种有效的方法来确保析构函数不会传播异常,并介绍了如何设计更好的资源管理接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

条款8 别让异常逃离析构函数

析构函数绝对不能吐出异常

C++不禁止析构函数抛出异常。
例如一个负责连接数据库的class

class DBConnection
{
public:
    ...
    static DBConnection create();
    void close();  //关闭连接 失败则会抛出异常
}

为了确保使用者不忘记在DBConnection上调用close,可以在析构函数中调用。设计一个资源管理的class。

class DBConn
{
public:
    ...
    ~DBConn()    //确保数据库关闭了
    {
        db.close();
    }
private:
    DBConnection db;
}

所以可以允许这样使用。

DBConn dbc(DBConnection::create());

但是如果close调用出现了异常,DBConn的析构函数则会传播这个异常。

有两个方法可以避免这个问题。

  • 若close抛出异常就结束程序。
DBConn::~DBConn()
{
    try{ db.close(); }
    catch(...)
    {
        //记录异常
        std::abort();  //直接终止程序运行
    }
}
  • 或者直接吞掉异常
DBConn::~DBConn()
{
    try{ db.close(); }
    catch(...)
    {
        //记录异常
    }
}
异常处理应该在普通函数中

一个比较好好的设计,就是重新设计DB接口,让客户有机会对可能出现的问题作出反应。

class DBConn
{
public:
    ...
    void close()
    {
        db.close();
        closed = true;
    }
    ~DBConn()
    {
        if(!closed)
        {
            try{
                db.close();
            }
            catch(...)
            {
                //制作运行记录,记录close调用失败
            }
        }
    }

private:
    DBConnection db;
    bool closed;
};

这样把close的任务交给了客户,析构函数只是一个双保险。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值