Effective C++读书笔记之条款08:别让异常逃离析构函数。

探讨C++中析构函数抛出异常的风险,提出通过管理类和异常捕获策略来确保资源正确释放的方法。

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

1、c++禁止析构函数吐出异常,但也不鼓励这样做。
来看实例:

class Widget
{
public:
	Widget();
	~Widget()
	{
	}
};
void g_doSomething()
{
	vector<Widget> arr;//arr为临时对象,函数结束自动销毁。
}

g_doSomething()中,析构函数在销毁资源的过程中吐出了一个异常,没有办法继续释放其他的资源,就会造成资源泄漏的严重后果。
所以要求我们不能够让异常逃离析构函数,至少要在析构函数遇到异常的时候能够终止程序,或者让它吞下异常。
2、那么如果你的析构函数必须执行一个动作,而且该动作可能在失败时候抛出异常,怎么办?
举个列子,class DBConnection负责数据库的连接:

class DBConnection
{
public:
	static DBConnection* Create()	//返回创建的DBConnection对象。
	{
		return new DBConnection;
	}
	void close()					//关闭联机,失败抛出异常。
	{
	}
};

其中一个合理的解决方案是创建一个用来管理的DBConnecton资源的class DBConnectMgr,并在析构函数中调用close。例如:

class DBConnectMgr					//用来管理DBConnection对象
{
public:
	DBConnectMgr(DBConnection* item)
	{
		m_db = *item;
	}
	~DBConnectMgr()
	{
		m_db.close();
	}
private:
	DBConnection m_db;
};

void g_doSomething2()
{
	DBConnectMgr dbm(DBConnection::Create());//创建DBConnection对象并且交给DBConnectMgr对象管理。

	//...	函数结束,需要销毁DBConnectMgr对象而调用~DBConnectMgr(),自动调用m_db.close()销毁DBConnection对象。
}

3、只要调用DBConnection 对象的close()调用成功,就大功告成。

但是如果该调用导致异常,DBConnectMgr析构函数就会传播异常,导致错误离开DBConnection析构函数,抛出难以驾驭的问题。

怎么避免这个问题?
可以修改DBConnectMgr类。不让析构函数来抛出异常,让用户自己来处理自己抛出的异常,避免因为析构函数抛出异常而导致出现不明的行为。

class DBConnectMgr					//用来管理DBConnection对象
{
public:
	DBConnectMgr(DBConnection* item)
	{
		m_db = *item;
	}
	~DBConnectMgr()
	{
		if (!m_bClosed)
		{
			try
			{
				m_db.close();
			}
			catch (...)			//close失败,就去记录异常处或者吞下异常。
			{
				//WriteLog()				记下close()调用失败。
				abort();				//  吞下异常
			}
		}
	}

public:
	void Close()
	{
		m_db.close();
		m_bClosed = true;
	}

private:
	DBConnection m_db;
	bool m_bClosed;
};

4.小结。

4.1、析构函数绝对不要吐出异常,如果调用析构函数可能会抛出异常,析构函数应该catch任何的异常,吞下他们(不传播),或者结束程序。
4.2、如果客户要对某个操作函数运行期间的异常作出反应,那么class应该提供了另一个普通的函数(而非在析构函数中)执行该操作。
4.3、不能在析构函数中调用可能出现异常的函数,因为析构函数有可能多次被调用,抛出异常可能会出现不可预知的后果。
4.4、如果想处理该异常,就应该自己定义一个普通的函数来处理该异常,比如自己写一个接口,让用户自己控制。

参考文章:https://www.cnblogs.com/MrZHj/p/4519707.html

入门萌新,浅知拙见,若有斧正,不胜感激。^ - ^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值