C++核心准则C.36:析构函数不应该失败

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


觉得本文有帮助?欢迎点赞并分享给更多的人。

阅读更多更新文章,请关注微信公众号【面向对象思考】

发布了408 篇原创文章 · 获赞 653 · 访问量 29万+

猜你喜欢

转载自blog.csdn.net/craftsman1970/article/details/104362249