![e2fb8482765bcdfa1b59a442e3f18134.png](https://i-blog.csdnimg.cn/blog_migrate/3ef01a5a8f81dc7583c5ce5dc2d7d501.jpeg)
C.36: A destructor may not fail析构函数不应该失败
Reason(原因)
In general we do not know how to write error-free code if a destructor should fail. The standard library requires that all classes it deals with have destructors that do not exit by throwing.
如果析构函数会失败,通常我们也不知道怎么写出没有错误的代码。 标准库要求它处理所有的类的析构函数都不要抛出异常。
Example(示例)
class X {
public:
~X() noexcept;
// ...
};
X::~X() noexcept {
// ...
if (cannot_release_a_resource) terminate();
// ...
}
Note(注意)
Many have tried to devise a fool-proof scheme for dealing with failure in destructors. None have succeeded to come up with a general scheme. This can be a real practical problem: For example, what about a socket that won't close? The writer of a destructor does not know why the destructor is called and cannot "refuse to act" by throwing an exception. See discussion. To make the problem worse, many "close/release" operations are not retryable. If at all possible, consider failure to close/cleanup a fundamental design error and terminate.
为了发明处理析构函数中的错误的可靠方法,人们已经进行了各种尝试。没有任何一种方法发展成通用的做法。这是一个真正的实践性问题:例如,socket不能关闭时怎么办?析构函数的编写者不知道析构函数因为什么被调用,而且不能通过抛出异常来拒绝这个动作。参见讨论(https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Sd-never-fail)。更为严重的是,很多“关闭/释放"操作都是不可重试的。如果可能的话,将关闭/释放时发生的错误当作基本的设计错误并终止执行。
Note(注意)
Declare a destructor noexcept. That will ensure that it either completes normally or terminate the program.
将析构函数定义为noexcept。这将保证要么正常结束析构,要么终止程序。
Note(注意)
If a resource cannot be released and the program may not fail, try to signal the failure to the rest of the system somehow (maybe even by modifying some global state and hope something will notice and be able to take care of the problem). Be fully aware that this technique is special-purpose and error-prone. Consider the "my connection will not close" example. Probably there is a problem at the other end of the connection and only a piece of code responsible for both ends of the connection can properly handle the problem. The destructor could send a message (somehow) to the responsible part of the system, consider that to have closed the connection, and return normally.
如果资源不能被释放而且程序有可能不失败,以某种方式(甚至可以是修改某些全局变量并寄希望于某些程序会注意并处理该问题)向程序的其他部分发出错误信号。需要充分意识到这个技术的特殊目的,而且容易发生错误。考虑示例“我的链接不会关闭"。有可能在链接的另一端存在问题,而且对于链接的两端来说,只存在一段代码负有正确地处理这个问题的责任。析构函数可以(以某种方式)象系统中负责处理错误的部分发送一条消息,同时认为我们已经关闭了链接并正确的返回了。
Note(注意)
If a destructor uses operations that may fail, it can catch exceptions and in some cases still complete successfully (e.g., by using a different clean-up mechanism from the one that threw an exception).
如果析构函数使用了可能失败的操作,有时候它可以在捕捉异常的同时正常结束处理(例如,通过某种除了抛出异常之外的特殊的清除机制)
Enforcement(实施建议)
(Simple) A destructor should be declared noexcept if it could throw.
(简单)如果可能抛出异常,那么析构函数应该声明为noexcept。
译者注:声明noexcept,编译器就不会生成异常的传递机制,这是一旦抛出异常,程序会直接中止。
原文链接
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c36-a-destructor-may-not-fail
觉得本文有帮助?请分享给更多人。
更多文章请关注微信公众号【面向对象思考】!
面向对象开发,面向对象思考!