throw expression
抛出表达式
向错误条件发出信号并执行错误处理程序。
句法
throw expression | (1) | |
---|---|---|
throw | (2) | |
解释
见试接块有关试一试
和捕获
%28异常处理程序%29块
1%29首,复制初始化大异常对象
在表达式%28中,这可能调用rvalue表达式的移动构造函数,并且复制/移动可能受复制省略%29,然后将控制转移到异常处理程序使用匹配类型,其复合语句或成员初始化程序列表是最近输入的,而不是由此执行线程退出的。即使复制初始化选择了移动构造函数,从lvalue复制初始化也必须是格式良好的,而且析构函数必须可以访问%28,因为C++14%29。
2%29重新引发当前处理的异常。放弃当前CATCH块的执行,并将控制传递给下一个匹配的异常处理程序%28,但不传递到同一TRY块之后的另一个CATCH子句:它的复合语句被认为是%27 EXECED%27%29,重用现有的异常对象:没有创建新的对象。只有在当前处理%28 it调用的异常时,才允许使用此窗体。std::terminate
如果不使用,%29。对象关联的CATCH子句。功能试块如果在构造函数上使用,必须通过重新抛出退出。
见std::terminate
和std::unexpected
用于处理异常处理过程中出现的错误。
异常对象
异常对象是由throw
表情。
类的类型。异常对象
是具有顶级表达式的静态类型。简历-资格移除。数组和函数类型分别调整为指针和指针到函数类型。如果异常对象
的类型为不完全类型或指向指向%28 cv限定%29空的指针以外的不完全类型的指针,则抛出表达式是编译时错误。如果表达式的类型是类类型,则即使在以下情况下,其复制/移动构造函数和析构函数也必须是可访问的。复制省略发生了。
与其他临时对象不同,当初始化CATCH子句参数时,异常对象被视为lvalue参数,因此它可以通过lvalue引用、修改和重新抛出来捕获。
异常对象一直持续到除通过重新抛出%28以外的上次CATCH子句退出为止(如果不是通过重新抛出),它将在CATCH子句%27s参数%29被销毁后立即销毁,或者直到最后一个std::exception_ptr
引用此对象被销毁%28,在这种情况下,异常对象就在std::exception_ptr
退货。
堆栈展开
一旦构造了异常对象,控制流将向后工作%28up调用堆栈%29,直到它到达试块,此时所有相关的参数catch
块按外观顺序与异常对象的类型进行比较,以找到匹配的%28(参见试着抓住有关此进程%29的详细信息。如果没有找到匹配项,则控制流将继续展开堆栈,直到下一次。try
封锁等等。如果找到匹配,则控制流跳到匹配。catch
封锁。
当控制流在调用堆栈上移动时,将为所有具有以下内容的对象调用析构函数。自动存储持续时间构造,但尚未销毁,因为相应的尝试块被输入,其构造函数的完成顺序相反。如果从局部变量的析构函数或回归语句时,也会调用函数返回的对象的析构函数。%28自C++14%29。
如果从构造函数引发异常,或从对象%28的析构函数引发%28稀有%29,而不管对象%27s存储时间为%29,则在C++14%29成员和基类之前,对所有完全构造的非静态非变量%28调用析构函数,并按构造函数的完成顺序相反。类联合类的变体成员只有在从构造函数展开的情况下才被销毁,如果活动成员在初始化和销毁之间发生了更改,则行为是未定义的。%28自C++14%29。
If a delegating constructor exits with an exception after the non-delegating constructor successfully completed, the destructor for this object is called. | (since C++11) |
---|
如果异常是从由新表达式,匹配解分配函数调用,如果可用的话。
这个过程称为堆栈展开
...
如果堆栈展开机制直接调用的任何函数在异常对象初始化后和异常处理程序启动之前退出,则为异常,std::terminate
叫做。这些职能包括破坏者具有自动存储持续时间的对象,其作用域退出,以及调用%28的异常对象的复制构造函数如果没有被剥夺%29来初始化随值捕获的参数.
如果抛出并没有捕获异常,则包括逃避std::thread
,然后是任何静态或线程本地对象的主函数和构造函数或析构函数。std::terminate
叫做。这是实现定义的任何堆栈展开是否发生在不明确的例外情况下。
注记
当重新抛出异常时,必须使用第二种形式来避免对象切片(%28典型%29)--在异常对象使用继承的情况下:
二次
try {
std::string("abc").substr(10 // throws std::length_error
} catch(const std::exception& e) {
std::cout << e.what() << '\n';
// throw e; // copy-initializes a new exception object of type std::exception
throw; // rethrows the exception object of type std::length_error
}
二次
抛出表达式被归类为prvalue表达式类型void
与任何其他表达式一样,它可能是另一个表达式中的子表达式,最常见的是条件算子*
二次
double f(double d)
{
return d > 1e7 ? throw std::overflow_error("too big") : d;
}
int main()
{
try {
std::cout << f(1e10) << '\n';
} catch (const std::overflow_error& e) {
std::cout << e.what() << '\n';
}
}
二次
关键词
throw
...
例
二次
#include <iostream>
#include <stdexcept>
struct A {
int n;
A(int n = 0): n(n) { std::cout << "A(" << n << ") constructed successfully\n"; }
~A() { std::cout << "A(" << n << ") destroyed\n"; }
};
int foo()
{
throw std::runtime_error("error"
}
struct B {
A a1, a2, a3;
B() try : a1(1), a2(foo()), a3(3) {
std::cout << "B constructed successfully\n";
} catch(...) {
std::cout << "B::B() exiting with exception\n";
}
~B() { std::cout << "B destroyed\n"; }
};
struct C : A, B {
C() try {
std::cout << "C::C() completed successfully\n";
} catch(...) {
std::cout << "C::C() exiting with exception\n";
}
~C() { std::cout << "C destroyed\n"; }
};
int main () try
{
// creates the A base subobject
// creates the a1 member of B
// fails to create the a2 member of B
// unwinding destroys the a1 member of B
// unwinding destroys the A base subobject
C c;
} catch (const std::exception& e) {
std::cout << "main() failed to create C with: " << e.what(
}
二次
产出:
二次
A(0) constructed successfully
A(1) constructed successfully
A(1) destroyed
B::B() exiting with exception
A(0) destroyed
C::C() exiting with exception
main() failed to create C with: error
二次
缺陷报告
以下行为更改缺陷报告追溯应用于先前发布的C++标准。
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1866 | C++14 | variant members were leaked on stack unwinding from constructor | variant members destroyed |
CWG 1863 | C++14 | copy constructor was not required for move-only exception objects when thrown, but copying allowed later | copy constructor required |
CWG 2176 | C++14 | throw from a local variable dtor could skip return value destructor | function return value added to unwinding |
另见
- 试接块
- 除说明符
- 异常规格
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。