理论上,但不是实际上,抛出函数应该被声明为noexcept吗?

时间:2015-08-04 12:26:45

标签: c++ function 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);
}

5 个答案:

答案 0 :(得分:15)

你对&#34;安全&#34;?的定义是什么?如果您在标记为noexceptnoexcept(true)的函数中抛出异常,那么您的程序将被终止(标准15.4.9)

  

每当抛出异常并且搜索处理程序(15.3)遇到a的最外面的块时   函数具有不允许异常的异常规范,然后,

     
      
  • 如果异常规范是动态异常规范,则函数std :: unexpected()是   叫(15.5.2),
  •   
  • 否则,调用函数std :: terminate()(15.5.1)。
  •   

只要这是可以接受的那么你就没事了。如果你不能容忍程序终止,那就不安全。

答案 1 :(得分:9)

很安全。如果发生异常,声明函数noexcept将导致程序立即终止(通过调用terminate())。只要没有抛出异常,一切都很好。

答案 2 :(得分:4)

我们没有完整的方案来确定确切该功能是否能够投掷。

您的假设是正确的:因为您正在执行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; }
}

答案 3 :(得分:2)

  

即使v.at(idx)理论上可以抛出out_of_range异常,但实际上不是由于边界检查?

理论上,它不可能。

如果你从理论上思考这个函数,那么边界检查就是你必须考虑的关于整个函数理论的一部分,所以唯一的理论方法就是如果有一个条件idx >= v.size()不是真的而且v.at(idx)扔了。

所以在你的陈述中,它理论上可以抛出&#34;是错的。

(在实践中,如果你在使用at()的实施过程中遇到错误,它可能会抛出,但是你遇到了更大的问题并且随着noexcept的爆炸而导致你做得可能更好。)

答案 4 :(得分:0)

big-O组织中的某个人可能已经聪明地从std::vector<int>派生了他的类,然后重载了size()和at()以满足他的喜好。然后在代码中的某个地方调用你的函数,但令每个人都惊讶的是程序终止而不是异常被高举。

确实很有用,但这不是关于std::vector<int> ......的问题,而是关于背后的编程实践。

不幸的是,你假设你的输入无法保证,这就是为什么不安全;至少在大型代码域中。