什么没有除了有用
What is noexcept useful for?
我看到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()
而不冒异常风险,则可能会暂时违反不变量并在以后恢复它们。如果可能引发异常,则库可能需要复制对象而不是移动它们。
标准C++库实现不太可能依赖于要noexcept(true)
的许多操作。它可能要检查的操作主要是那些涉及移动物体的操作,即:
- 类的析构函数
- (注意析构函数默认
noexcept(true)
即使没有任何声明;如果你有可能抛出的析构函数,你需要这样声明它,例如:T::~T() noexcept(false)
(。 - 移动运算符,即移动构造(
T::T(T&&)
(和移动分配(T::operator=(T&&)
(。 - 类型的
swap()
操作(swap(T&, T&)
,可能还有成员版本T::swap(T&)
(。
如果这些操作中的任何一个偏离默认值,则应相应地声明它以获得最有效的实现。这些操作的生成版本声明它们是否根据用于成员和基的相应操作引发异常。
尽管我可以想象将来可能会添加某些操作或由某些特定库添加某些操作,但我可能不会暂时将操作声明为noexcept
。如果出现其他功能,noexcept
可以声明它们(并可能根据需要进行更改(。
程序可能崩溃的原因是noexcept
告诉优化器您的代码不会抛出。如果是这样 - 好吧,没有办法预测优化代码会发生什么。
至于MSVC++,您必须检查当他们实现noexcept
时会发生什么。从标准的角度来看,SEH 是未定义的行为。访问受保护的内存现在可能已经崩溃。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 警告处理为错误这里有什么问题
- 什么时候调用组成单元对象的析构函数
- #定义c-预处理器常量..我做错了什么
- 努力将整数转换为链表。不知道我在这里做错了什么
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 什么时候在C++中返回常量引用是个好主意
- P1008("prohibit aggregates with user-declared constructors")在实践中什么时候有用?
- std::bit_cast 和 std::start_lifetime_as 之间有什么有用的区别吗?
- 在不编写显式 setter 的情况下修改私有类数据成员的便捷方法是什么?模板有用吗?
- 是什么让这种图像处理有用[加速C++]
- lambda函数什么时候对C++中的类有用
- 什么是野牛,为什么它有用
- 什么是清除和设置用于的位以及为什么有用
- 什么是 std::ref 在这个函数中有用
- 什么没有除了有用
- 这个布尔运算符在C++中实际做了什么?这个奇怪的东西怎么会有用呢
- dynamic_cast<无效*>什么时候有用?
- old的-u选项是如何工作的,它什么时候有用
- 键值关联容器中的顺序是有用的用例是什么