从析构函数中抛出异常 [英] throwing exceptions out of a destructor

查看:262
本文介绍了从析构函数中抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大多数人说永远不会从析构函数中抛出异常 - 这样做会导致未定义的行为。 Stroustrup指出,向量析构函数显式地调用每个元素的析构函数,这意味着如果一个元素析构函数抛出,向量销毁失败...没有什么好的方法来防止从析构函数抛出的异常,所以如果一个元素析构函数抛出(来自附录E3.2),则库不能保证。

Most people say never throw an exception out of a destructor - doing so results in undefined behavior. Stroustrup makes the point that "the vector destructor explicitly invokes the destructor for every element. This implies that if an element destructor throws, the vector destruction fails... There is really no good way to protect against exceptions thrown from destructors, so the library makes no guarantees if an element destructor throws" (from Appendix E3.2).

这篇文章似乎不是这样说的 - 抛出的析构函数或多或少是好的。

This article seems to say otherwise - that throwing destructors are more or less okay.

所以我的问题是这 - 如果从析构函数抛出会导致未定义的行为,你如何处理在析构函数期间发生的错误?

So my question is this - if throwing from a destructor results in undefined behavior, how do you handle errors that occur during a destructor?

如果在清理操作期间发生错误,您是否忽略它?如果它是一个错误,可能可以处理堆栈,但不是在析构函数中,不是有意义的抛出析构函数异常?

If an error occurs during a cleanup operation, do you just ignore it? If it is an error that can potentially be handled up the stack but not right in the destructor, doesn't it make sense to throw an exception out of the destructor?

显然这些错误很少,但是可能。

Obviously these kinds of errors are rare, but possible.

推荐答案

从析构函数中抛出异常是很危险的。

如果另一个异常已经传播,应用程序将终止。

Throwing an exception out of a destructor is dangerous.
If another exception is already propagating the application will terminate.

#include <iostream>

class Bad
{
    public:
        ~Bad()
        {
            throw 1;
        }
};

int main()
{
    try
    {
        Bad   bad;
    }
    catch(...)
    {
        std::cout << "Print This" << std::endl;
    }

    try
    {
        Bad   bad;
        throw 2;
    }
    catch(...)
    {
        std::cout << "Never print this " << std::endl;
    }
}

这基本上归结为:

任何危险的(即可以抛出异常)应该通过公共方法(不一定是直接)来完成。然后,类的用户可以通过使用公共方法并捕获任何潜在的异常来处理这些情况。

Anything dangerous (i.e. that could throw an exception) should be done via public methods (not necessarily directly). The user of your class can then potentially handle these situations by using the public methods and catching any potential exceptions.

然后析构函数将通过调用这些方法如果用户没有明确这样做),但任何异常抛出被捕获和删除(尝试修复问题后)。

The destructor will then finish off the object by calling these methods (if the user did not do so explicitly), but any exceptions throw are caught and dropped (after attempting to fix the problem).

用户。如果用户能够纠正异常,它们将手动调用相应的函数并处理任何错误。如果对象的用户不担心(因为对象将被销毁),那么析构函数将被用来处理业务。

So in affect you pass the responsibility onto the user. If the user is in a position to correct exceptions they will manually call the appropriate functions and processes any errors. If the user of the object is not worried (as the object will be destroyed) then the destructor is left to take care of business.

std :: fstream

std::fstream

close()方法可能会抛出异常。
如果文件已经被打开,d​​estruct调用close(),但是确保任何异常都不会传播到析构函数之外。

The close() method can potentially throw an exception. The destructs calls close() if the file has been opened but makes sure that any exceptions do not propagate out of the destructor.

一个文件对象想要对与关闭文件相关的问题进行特殊处理,他们将手动调用close()和处理任何异常。如果在另一方面他们不在乎,那么析构函数将被处理的情况。

So if the user of a file object wants to do special handling for problems associated to closing the file they will manually call close() and handle any exceptions. If on the other hand they do not care then the destructor will be left to handle the situation.

Scott Myers在他的书Effective C ++

Scott Myers has an excellent article about the subject in his book "Effective C++"

显然也在更有效的C ++中

项目11:防止异常离开析构函数

Apparently also in "More Effective C++"
Item 11: Prevent exceptions from leaving destructors

这篇关于从析构函数中抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆