理论上(但实际上)抛出函数是否应该声明为 noexcept?
Should a theoretically, but not practically, throwing function be declared noexcept?
声明以下函数是否安全 noexcept
即使 v.at(idx)
理论上可以抛出 out_of_range
异常,但实际上不是由于边界检查?
int get_value_or_default(const std::vector<int>& v, size_t idx) noexcept {
if (idx >= v.size()) {
return -1;
}
return v.at(idx);
}
很安全。如果发生异常,声明函数 noexcept
将导致程序立即终止(通过调用 terminate()
)。只要不抛出异常就没问题。
你对"safe"的定义是什么?如果您在标记为 noexcept
或 noexcept(true)
的函数中抛出异常,那么您的程序将被终止(标准 15.4.9)
Whenever an exception is thrown and the search for a handler (15.3) encounters the outermost block of a
function with an exception-specification that does not allow the exception, then,
- if the exception-specification is a dynamic-exception-specification, the function std::unexpected() is
called (15.5.2),
- otherwise, the function std::terminate() is called (15.5.1).
只要能接受就没问题。如果你不能容忍程序终止那么它是不安全的。
我们没有完整的场景来确切地确定该函数是否能够抛出。
您的假设虽然是正确的:因为您正在做 std::vector::at
无论如何都会做的事情,所以在给定的上下文中 不太可能 有害。然而,一般来说,这样的函数 可能 是无效因素的主题,因此可能会抛出异常。这些可能是线程、进程或信号,它们可能会交错执行可能修改 std::vector
的代码,这些代码无法安全处理,std::vector::at
.
也不能
如果你也想考虑这些可能性,你需要有类似
的东西
int get_value_or_default(const std::vector<int>& v, size_t idx) noexcept
{
try { return v.at(idx); }
catch (std::out_of_range const& e) { return -1; }
}
even though v.at(idx)
could theoretically throw a out_of_range
exception, but practically not due to the bounds check?
理论上不能。
如果您从理论上考虑该函数,那么边界检查是您必须考虑的关于该函数整个理论的一部分,因此它可能抛出的唯一理论上的方法是是否存在idx >= v.size()
不成立但 v.at(idx)
抛出的条件。
所以在你的陈述中 "could theoretically throw" 是错误的。
(实际上它可能会抛出,如果你在使用 at()
的实现中有一个错误,但是你会遇到更大的问题并且爆炸,因为 noexcept
可能会导致你这样做可能会更好)。
big-O 组织中的某个人可能做得很聪明,从 std::vector<int>
中导出了他的 class,然后重载了 size() 和 at() 以按照他的喜好进行抛出。然后在代码的某处调用了您的函数,但令所有人惊讶的是程序终止了,而不是异常被更高层捕获。
确实牵强,但这不是一个关于std::vector<int>
...的问题,而是关于背后的编程实践。
不幸的是,您假设有关您的输入的事情无法得到保证,这就是为什么它 不安全;至少在大型代码域中。
声明以下函数是否安全 noexcept
即使 v.at(idx)
理论上可以抛出 out_of_range
异常,但实际上不是由于边界检查?
int get_value_or_default(const std::vector<int>& v, size_t idx) noexcept {
if (idx >= v.size()) {
return -1;
}
return v.at(idx);
}
很安全。如果发生异常,声明函数 noexcept
将导致程序立即终止(通过调用 terminate()
)。只要不抛出异常就没问题。
你对"safe"的定义是什么?如果您在标记为 noexcept
或 noexcept(true)
的函数中抛出异常,那么您的程序将被终止(标准 15.4.9)
Whenever an exception is thrown and the search for a handler (15.3) encounters the outermost block of a function with an exception-specification that does not allow the exception, then,
- if the exception-specification is a dynamic-exception-specification, the function std::unexpected() is called (15.5.2),
- otherwise, the function std::terminate() is called (15.5.1).
只要能接受就没问题。如果你不能容忍程序终止那么它是不安全的。
我们没有完整的场景来确切地确定该函数是否能够抛出。
您的假设虽然是正确的:因为您正在做 std::vector::at
无论如何都会做的事情,所以在给定的上下文中 不太可能 有害。然而,一般来说,这样的函数 可能 是无效因素的主题,因此可能会抛出异常。这些可能是线程、进程或信号,它们可能会交错执行可能修改 std::vector
的代码,这些代码无法安全处理,std::vector::at
.
如果你也想考虑这些可能性,你需要有类似
的东西int get_value_or_default(const std::vector<int>& v, size_t idx) noexcept
{
try { return v.at(idx); }
catch (std::out_of_range const& e) { return -1; }
}
even though
v.at(idx)
could theoretically throw aout_of_range
exception, but practically not due to the bounds check?
理论上不能。
如果您从理论上考虑该函数,那么边界检查是您必须考虑的关于该函数整个理论的一部分,因此它可能抛出的唯一理论上的方法是是否存在idx >= v.size()
不成立但 v.at(idx)
抛出的条件。
所以在你的陈述中 "could theoretically throw" 是错误的。
(实际上它可能会抛出,如果你在使用 at()
的实现中有一个错误,但是你会遇到更大的问题并且爆炸,因为 noexcept
可能会导致你这样做可能会更好)。
big-O 组织中的某个人可能做得很聪明,从 std::vector<int>
中导出了他的 class,然后重载了 size() 和 at() 以按照他的喜好进行抛出。然后在代码的某处调用了您的函数,但令所有人惊讶的是程序终止了,而不是异常被更高层捕获。
确实牵强,但这不是一个关于std::vector<int>
...的问题,而是关于背后的编程实践。
不幸的是,您假设有关您的输入的事情无法得到保证,这就是为什么它 不安全;至少在大型代码域中。