一个只能由于整数溢出而失败的函数应该是 noexcept 吗?
Should a function which can fail only due to integer overflow be noexcept?
完整的问题符合标题。这是一个简单的例子:
constexpr int increment(int const value) /*noexcept?*/ {
return value + 1;
}
据我所知,noexcept
在决定是否用它标记一个函数时应该被解释为"nofail"。因此,throw
ing 的不可能情况并不是唯一必须考虑的推理。
我没有使用 C++20,所以我的签名溢出还没有定义。 :)
As far as I know, noexcept should be interpreted as "nofail"
这是不正确的。 noexcept
字面上的意思是"I promise this function will never throw an exception."还有无数其他类型的失败,例如段错误,非法指令,纯虚函数的调用,整数被零除,更不用说"Bob in accounting told me all our customer numbers consist only of digits, but I just found out our very first customer's ID was actually Q001 and it doesn't parse." [=其中 22=] 必然会导致异常,并且有符号整数也不会溢出,因此以这些方式失败的函数仍然可以是 noexcept
,即使它们可能会失败——它们只是不能抛出 C++ 异常。
你可能会想,"What happens if an exception is thrown by a noexcept
function?"在那种情况下,std::terminate()
会被调用,你的程序就会结束。
noexcept
只是你的 "promise" 函数永远不会允许从它逃逸的异常,意思是如果发生这种情况,你的代码将通过调用 std::terminate
而不是让异常逃逸。
知道一个函数永远不会抛出异常允许编译器在调用者中生成更多 efficient/compact 代码并允许创建更健壮的软件(当一些不被设计为handle happens 比让 运行 做随机事情的软件更健壮......这是许多年轻程序员感到困惑的事情)。
不幸的是,异常并不是 C++ 中失败的唯一来源,在 "undefined behavior" 的房间里有大象,所以用 C++ 编写真正健壮的软件是一项极其困难的任务,因为您还应该避免每个潜在的未定义行为(这几乎是不可能的;例如可以生成未定义的行为任何整数数学运算、任何迭代器的使用、任何数组访问、任何指针访问、任何未初始化的变量、对同一内存的任何多个未排序的副作用,任何竞争条件...等等等等)。
当然请注意,即使是没有未定义行为但保证运行时错误的完美 "safe" 低级语言也无法 "silver bullet" 编写真正健壮的软件。原因是,如果您的算法没有按照您希望的方式处理所有呈现给它们的案例,那么您可以在更合乎逻辑的层面上进行某种 "undefined behavior"。
换句话说,如果您的程序由于 C++ 未定义行为或因为您捕获并处理了一个异常而不是您认为它来自的地方(什么nothrow
想保护您免受)或因为您的代码根本没有考虑和处理客户联系数据可能具有的空 phone 号码。
未定义行为的概念当然不好,之所以存在是因为允许生成更快的代码。在我看来,这应该是编程语言的默认值是有争议的;其他语言更喜欢更安全的默认环境,而是允许特别标记的 "fast and dangerous" 区域,要求程序员永远不会犯任何低级错误。
完整的问题符合标题。这是一个简单的例子:
constexpr int increment(int const value) /*noexcept?*/ {
return value + 1;
}
据我所知,noexcept
在决定是否用它标记一个函数时应该被解释为"nofail"。因此,throw
ing 的不可能情况并不是唯一必须考虑的推理。
我没有使用 C++20,所以我的签名溢出还没有定义。 :)
As far as I know, noexcept should be interpreted as "nofail"
这是不正确的。 noexcept
字面上的意思是"I promise this function will never throw an exception."还有无数其他类型的失败,例如段错误,非法指令,纯虚函数的调用,整数被零除,更不用说"Bob in accounting told me all our customer numbers consist only of digits, but I just found out our very first customer's ID was actually Q001 and it doesn't parse." [=其中 22=] 必然会导致异常,并且有符号整数也不会溢出,因此以这些方式失败的函数仍然可以是 noexcept
,即使它们可能会失败——它们只是不能抛出 C++ 异常。
你可能会想,"What happens if an exception is thrown by a noexcept
function?"在那种情况下,std::terminate()
会被调用,你的程序就会结束。
noexcept
只是你的 "promise" 函数永远不会允许从它逃逸的异常,意思是如果发生这种情况,你的代码将通过调用 std::terminate
而不是让异常逃逸。
知道一个函数永远不会抛出异常允许编译器在调用者中生成更多 efficient/compact 代码并允许创建更健壮的软件(当一些不被设计为handle happens 比让 运行 做随机事情的软件更健壮......这是许多年轻程序员感到困惑的事情)。
不幸的是,异常并不是 C++ 中失败的唯一来源,在 "undefined behavior" 的房间里有大象,所以用 C++ 编写真正健壮的软件是一项极其困难的任务,因为您还应该避免每个潜在的未定义行为(这几乎是不可能的;例如可以生成未定义的行为任何整数数学运算、任何迭代器的使用、任何数组访问、任何指针访问、任何未初始化的变量、对同一内存的任何多个未排序的副作用,任何竞争条件...等等等等)。
当然请注意,即使是没有未定义行为但保证运行时错误的完美 "safe" 低级语言也无法 "silver bullet" 编写真正健壮的软件。原因是,如果您的算法没有按照您希望的方式处理所有呈现给它们的案例,那么您可以在更合乎逻辑的层面上进行某种 "undefined behavior"。
换句话说,如果您的程序由于 C++ 未定义行为或因为您捕获并处理了一个异常而不是您认为它来自的地方(什么nothrow
想保护您免受)或因为您的代码根本没有考虑和处理客户联系数据可能具有的空 phone 号码。
未定义行为的概念当然不好,之所以存在是因为允许生成更快的代码。在我看来,这应该是编程语言的默认值是有争议的;其他语言更喜欢更安全的默认环境,而是允许特别标记的 "fast and dangerous" 区域,要求程序员永远不会犯任何低级错误。