[英]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.