在catch块之外使用"throw;"语句会发生什么?

21

我刚刚偶然发现了这段代码:

void somefunction()
{
   throw;
}

我想知道:这是什么意思?


3
请勿使用与 Visual Studio 或任何“可视”的 C++ 相关的标签。请不要用具体的框架标签来标记通用的 C++ 问题。请注意,此问题与 Visual Studio 或任何“可视”的 C++ 无关。 - P Shved
@Pavel Shved:如果有适用的某种语言扩展,这个问题可能与VC++有关。在这种情况下,最好基于此回答它,并指出根据标准的答案。 - David Thornley
@David,@Tobias,如果你们不确定的话,最好不要将问题标记为VC相关。如果它是语言扩展,社区会适当地重新标记它。 - P Shved
@Pavel:我认为如果提问者不确定的话,我更愿意看到它被标记为与VC++相关。这肯定是有争议的。在任何情况下,Tobias,请确保在需要时指定平台,尽管现在具体在哪里仍存在争议。 - David Thornley
4个回答

32

大概意思是 somefunction() 函数只能在某个 catch 块内部被调用。这种情况下,当执行throw;时会有一个异常处于活动状态,此时当前异常会被重新抛出,以便由下一个可以处理该异常类型的外层处理程序来捕获。

如果在没有异常处于活动状态时执行 throw;,则会调用 terminate()(参见 N4810, §[expr.throw]/4)。


9

它重新抛出当前活动的异常。 只有在catch块中调用它(可能是间接调用)才有意义。 这样做:

#include <iostream>
using namespace std;

void f() {
    throw;
}

int main() {
    try {
        try {
            throw "foo";
        }
        catch( ... ) {
            f();
        }
    }
    catch( const char * s ) {
        cout << s << endl;
    }
}

打印 "foo"。


5
对于throw,"外部"或"内部"catch块的概念是在运行时而不是编译时定义的,这一点请注意。因此,如果在运行时上下文中执行throw,并且该上下文处于catch块的运行时上下文中,则throw将按预期工作。否则,将调用terminate()
实际上,如果您仔细查看C++异常在语言规范中的定义方式,就会发现关于它们的很多内容都是以运行时术语来定义的。有时甚至看起来与C++不太相似。

不,我没有假设这样的事情。但是我没有充分评论该函数的使用。对于误解,我很抱歉。 - Tobias Langner

3
人们已经解释了它的含义,但知道为什么会出现它可能有用。这是一种构建“通用”异常处理程序的有用方法,可以根据异常类型处理异常,以减少重复代码的数量。
因此,如果我们采用Neil's example并扩展f()可能正在执行的内容,我们可能会得到一个类似于我在this answer中提出的LogKnownException()函数的实现。
如果您正在一个喜欢在各个地方记录各种异常的团队中工作,那么与其在所有这些地方拥有大量的catch块(甚至更糟的是宏),不如拥有一个简单的catch块,它看起来像这样。
catch(...)
{
   LogKnownException();
}  

尽管我预计我会更改之前的LogKnownException()示例,但我希望它只允许不想记录的异常传播并继续以未处理的方式进行。
我并不是建议这样做一定是好的,只是指出这是你可能看到使用这种结构的地方。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接