繁体   English   中英

std::accumulate 可以抛出吗?

[英]can std::accumulate throw?

对于C ++引用std::accumulate没有提到任何异常要由可能抛出std::accumulate ,还是它的定义不包含noexcept 假设使用不抛出的类型和操作,在声明为noexcept的成员函数中使用std::accumulate是安全的,还是会在 UB 中产生?

例如:

#include <iostream>
#include <numeric>
#include <vector>

class A {
  std::vector<int> m_v;
public:
  A(std::size_t N) : m_v(N, 1) { }
  int sum() const noexcept { return std::accumulate(m_v.begin(), m_v.end(), 0); }
};

int main()
{
     A x{3};
     std::cout << x.sum() << std::endl;
     return 0;
}

是否A::sum()声明为noexcept是 UB 的来源?

std::accumulate()有先决条件,例如,从范围的开始可以到达范围的末尾。 到目前为止,标准库还没有将noexcept放在具有前提条件的函数上(至少,一般情况下没有;可能有特殊情况),因为调试实现可以​​断言存在问题,例如,通过抛出异常:当未定义的行为被触发是未定义的,如果他们愿意的话,实现可以自由定义任何一个。

此外,允许std::accumulate()调用的任何函数抛出,即任何noexcept声明都需要有条件。 我认为算法一般不太可能获得相应的noexcept声明。

由于规范没有提到std::accumulate()在合约内调用时抛出的任何情况,如果被调用的操作都没有抛出,它就不会抛出。

是的,一般来说是可以的。

首先,可通过模板参数自定义且std::accumulate必须执行的操作可以抛出。

但除此之外,如果标准库函数没有非抛出异常规范并且函数的描述没有另外说明,则标准确实允许实现抛出实现定义的异常,请参阅[res.on.exception .处理]/4

话虽如此,如果在您的示例中使用std::accumulate会抛出std::accumulate ,我会感到惊讶。 不需要动态分配,因此不需要潜在的std::bad_alloc抛出,这是实现定义异常的最有可能的候选者。 int上的求和、复制和/或移动操作也是非抛出的。

在任何情况下,如果在函数内部抛出异常,向函数添加noexcept都不会导致未定义的行为。 相反,它是明确定义的,如果异常到达noexcept函数的外部作用域,将调用std::terminate ,默认情况下会中止程序,但可以在某种程度上进行自定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM