我看到C++ 11增加了noexcept
关键字,但我不太明白它有什么用。
如果函数在不应该抛出异常时抛出异常-为什么我想让程序崩溃?
那我什么时候该使用它呢?
此外,如果使用/Eha进行编译和使用_set_se_translator
,它将如何运作?这意味着任何一行代码都可能抛出c++异常-因为它可能会抛出SEH异常(由于访问受保护的内存),并将被转换为c++异常。
那时会发生什么?
我看到C++ 11增加了noexcept
关键字,但我不太明白它有什么用。
如果函数在不应该抛出异常时抛出异常-为什么我想让程序崩溃?
那我什么时候该使用它呢?
此外,如果使用/Eha进行编译和使用_set_se_translator
,它将如何运作?这意味着任何一行代码都可能抛出c++异常-因为它可能会抛出SEH异常(由于访问受保护的内存),并将被转换为c++异常。
那时会发生什么?
noexcept
的主要用途是用于泛型算法,例如调整std::vector<T>
大小时:为了实现移动元素的高效算法,需要提前知道没有任何移动会抛出异常。如果移动元素可能会抛出异常,则需要复制元素。使用noexcept(expr)
运算符,库实现可以确定特定操作是否可能抛出异常。不抛出异常的操作属性成为合同的一部分:如果违反了该合同,则所有赌注都将被取消,并且可能没有办法恢复有效状态。在造成更多损害之前放弃是自然的选择。noexcept
操作不抛出异常的知识,还需要声明函数为此类函数。为此,您可以使用noexcept
、throw()
或noexcept(expr)
与常量表达式。在实现通用数据结构时,使用表达式是必要的:通过表达式,可以确定任何类型相关操作是否可能引发异常。std::swap()
的声明类似于这样:template <typename T>
void swap(T& o1, T& o2) noexcept(noexcept(T(std::move(o1)) &&
noexcept(o1 = std::move(o2)));
noexcept(swap(a, b))
,库可以选择不同的高效实现某些操作:如果它可以在不引发异常的情况下只是简单地 swap()
,则可能会暂时违反不变量并稍后恢复它们。如果可能会抛出异常,则库可能需要复制对象而不是在它们之间移动。noexcept(true)
是不太可能的。它将检查的操作可能主要涉及移动对象,即:
noexcept(true)
;如果您有可能引发异常的析构函数,您需要将其声明为这样,例如:T::~T() noexcept(false)
)。T::T(T&&)
)和移动赋值运算符(T::operator=(T&&)
)。swap()
操作(swap(T&, T&)
和可能的成员版本 T::swap(T&)
)。noexcept
。如果出现其他函数,它们作为 noexcept
有所不同,则可以在将来声明它们(并根据需要进行更改)。noexcept
告诉优化器你的代码不会抛出异常。如果它确实抛出了异常,那么就没有办法预测优化后的代码会发生什么。noexcept
时会发生什么。从标准的角度来看,SEH是未定义行为。访问受保护的内存已经可以导致程序崩溃。struct foo { int i_34568790845609; }
,即使该特定结构不出现在其中。然而,这些规则绝对不允许SEH。一组结构是无限的,并不意味着它包含所有东西。偶数集合是无限的,但不包含3。 - MSalters
noexcept
来告诉系统一个函数不会抛出异常。如果它仍然抛出异常(因为某些开发人员很蠢,要么直接抛出异常,要么间接调用某些没有try
-catch
块的东西),那么你认为系统应该怎么做?显然,如果访问了不允许访问的内存,你的代码将以某种方式崩溃,那么如果它以这种或那种方式崩溃有什么区别呢? - Mats Peterssonstd::terminate
,这更像是一种“有序中止”而不是崩溃(这基本上意味着需要生成额外的调用terminate
的代码)。 - Damon