std::accumulate
的c ++参考未提及std::accumulate
可能抛出的任何异常,但其定义中不包含noexcept
。假设有人使用不会抛出的类型和操作,可以安全地在声明为std::accumulate
的成员函数中使用noexcept
,还是有人在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来源?
答案 0 :(得分:2)
std::accumulate()
上有一些先决条件,例如,从范围的起点可以到达范围的终点。到目前为止,标准库还没有将noexcept
放在具有前提条件的函数上(至少不是一般情况;可能会有特殊情况),因为调试实现可以断言存在问题,例如,抛出异常:触发未定义行为时会发生未定义的情况,实现者可以自由定义任何行为。
此外,允许std::accumulate()
调用的任何函数都可以抛出,即,任何noexcept
声明都必须是有条件的。我认为算法一般不会获得相应的noexcept
声明。
由于规范中没有提到在合同内调用std::accumulate()
时抛出的情况,因此如果没有被调用的操作都抛出,则不会抛出。
答案 1 :(得分:1)
是的,通常可以。
首先可以通过模板参数自定义并且span { color: red}
必须执行的操作会抛出。
但是,除此之外,如果标准库函数没有非抛出异常规范,并且该函数的描述未另外说明,那么该标准确实允许实现抛出实现定义的异常,请参见{{3 }}。
话虽如此,如果您的示例中使用<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>We have cows in our farm cowshed</h2>
<h2>C++ Apps $var$ in $var$moretext</h2>
,我会感到惊讶。不需要动态分配,因此不需要std::accumulate
的潜在抛出,并且这是实现定义的异常的最有可能的候选者。在std::accumulate
上的求和,复制和/或移动操作也没有抛出。
在任何情况下,如果向函数中添加std::bad_alloc
,如果在其中引发异常,则不会导致未定义的行为。取而代之的是,如果异常到达int
函数的外部范围,则将明确定义noexcept
,它将被调用,默认情况下将中止程序,但可以在一定程度上进行自定义。