throw()
除了在运行时和noexcept
编译时分别检查之外,还有什么区别吗?
这篇 Wikipedia C++11 文章建议弃用 C++03 抛出说明符。
为什么这样,noexcept
有足够的能力在编译时涵盖所有这些?
异常说明符已被弃用,因为异常说明符通常是一个糟糕的主意。noexcept
之所以添加它,是因为它是异常说明符的一种合理有用的用法:知道函数何时不会抛出异常。因此它变成了一个二元选择:会抛出的函数和不会抛出的函数。
noexcept
添加而不是仅仅删除所有抛出说明符,而不是throw()
因为noexcept
更强大。noexcept
可以有一个编译时解析为布尔值的参数。如果布尔值是真的,那么noexcept
棒。如果布尔值是假的,那么noexcept
不会粘住并且函数可能会抛出。
因此,您可以执行以下操作:
struct<typename T>
{
void CreateOtherClass() { T t{}; }
};
会CreateOtherClass
抛出异常吗?它可能,如果T
的默认构造函数可以。我们怎么讲?像这样:
struct<typename T>
{
void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
因此,CreateOtherClass()
如果给定类型的默认构造函数抛出,将抛出。这解决了异常说明符的主要问题之一:它们无法向上传播调用堆栈。
你不能用throw()
.
noexcept
在编译时不检查。
实现不应仅仅因为表达式在执行时抛出或可能抛出包含函数不允许的异常而拒绝表达式。
当一个函数被声明noexcept
或throw()
试图抛出异常时,唯一的区别是一个调用terminate
和另一个调用unexpected
,并且后一种异常处理方式已被有效地弃用。
std::unexpected()
当违反动态异常规范时由 C++ 运行时调用:从其异常规范禁止此类异常的函数抛出异常。
std::unexpected()
也可以直接从程序中调用。
无论哪种情况,std::unexpected
调用当前安装的std::unexpected_handler
. 默认std::unexpected_handler
调用std::terminate
.