Exceptions
例外
异常处理提供了一种将控制和信息从程序执行过程中的某个点传输到与执行%28之前传递的点相关联的处理程序的方法--换句话说,异常处理传输控制调用堆栈%29。
异常可以由抛出,,,动态[医]铸造,,,类型,,,新表达式,,,分配函数,以及任何指定的标准库函数,这些函数将抛出异常以指示某些错误条件(%28)。std::vector::at
,,,std::string::substr
,等...%29。
为了捕获异常,抛出表达式必须位于试块或者在从try块调用的函数中,并且必须有捕获条款它与异常对象的类型匹配。
在声明函数时,异常规格和除说明符可以提供以限制函数可能抛出的异常类型。
异常处理过程中出现的错误由std::terminate
和std::unexpected
...
使用
虽然抛出表达式可用于将控件传输到执行堆栈上的任意代码块,但出于类似于std::longjmp
%29,它的预期使用是错误处理。
错误处理
抛出异常用于向来自函数的错误发出信号,其中“错误”通常仅限于以下内容[1][2][3]*
- 未能满足后置条件,例如未能生成有效的返回值对象
- 未能满足必须调用的另一个函数的先决条件
- %28对于非私有成员函数%29失败到%28 re%29建立类不变量
特别是,这意味着构造函数%28的故障也参见雷伊%29,大多数操作符应该通过抛出异常来报告。
此外,所谓的宽合同
函数使用异常来指示不可接受的输入,例如,std::string::at
没有先决条件,但抛出异常以指示超出范围的索引。
异常安全
在错误条件由函数报告之后,可以提供关于程序状态的附加保证。以下四个级别的例外保证是公认的[4][5][6],它们是彼此严格的超集:
不抛出%28或NoFailure%29异常保证
-函数从不抛出异常。不抛出%28错误是通过其他方法报告的,或者隐藏%29预期为破坏者以及在堆栈展开过程中可能调用的其他函数。大破坏者是不,除了默认情况下。%28由于C++11%29 Nofail%28函数总是成功的%29被期望掉期,移动构造器,以及那些提供强异常保证的函数所使用的其他功能。
强例外保证
--如果函数抛出异常,程序的状态将回滚到函数调用之前的状态。%28例如,std::vector::push_back
%29
基本例外保证
--如果函数抛出异常,则程序处于有效状态。它可能需要清理,但所有不变量都完好无损。
无例外保证
--如果函数抛出异常,程序可能处于无效状态:可能发生资源泄漏、内存损坏或其他破坏不变的错误。
此外,通用组件还可以提供例外中立担保
如果从模板参数%28e.g引发异常。从Compare
功能对象std::sort
的构造函数T
在std::make_shared
%29,它被传播到调用者,没有变化。
异常对象
虽然任何完整类型的对象和指向void的cv指针都可以作为异常对象抛出,但所有标准库函数都会按值抛出匿名临时对象,这些对象的类型直接或间接地派生为%28std::exception
用户定义的异常通常遵循这种模式。[7][8][9]
为了避免不必要地复制异常对象和对象切片,CATCH子句的最佳实践是通过引用捕获。[10][11][12][13]
参考文献
- H.萨特%282004%29“何时及如何使用例外情况”在Dobb%27S
- H.Sutter,A.Alexandrescu%282004%29,“C++编码标准”,第70项
- C++核心准则一.10
- B.Stroustrup%282000%29,“C++编程语言”附录E“
- H.Sutter%282000%29“例外C++”
- D.阿布拉哈姆斯%282001%29“泛型组件中的异常安全”
- D.阿布拉哈姆斯%282001%29“错误和异常处理”
- isocpp.org超级常见问题解答“我该扔什么?”
- C++核心准则E.14
- C++核心准则E.15
- S.Meyers%281996%29“更有效的C++”项目13
- isocpp.org超级常见问题解答“我该抓什么?”
- H.Sutter,A.Alexandrescu%282004%29“C++编码标准”项目73
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。