std::accumulate 可以扔吗?
can std::accumulate throw?
std::accumulate
的 c++ 参考没有提到 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
必须执行的所有操作都可以抛出。
但即使除此之外,如果标准库函数没有非抛出异常规范并且函数的描述没有另外说明,则标准确实允许实现抛出实现定义的异常,请参阅[res.on.exception.handling]/4.
也就是说,如果在您的示例中使用 std::accumulate
会抛出异常,我会感到惊讶。不需要动态分配,因此不需要潜在的 std::bad_alloc
抛出,这是实现定义的异常最有可能的候选者。 int
上的求和、复制 and/or 移动操作也不会抛出。
在任何情况下,如果函数内部抛出异常,将 noexcept
添加到函数中不会导致未定义的行为。相反,明确定义的是,如果异常到达 noexcept
函数的外部范围,将调用 std::terminate
,默认情况下会中止程序,但可以在某种程度上进行自定义。
std::accumulate()
有先决条件,例如,范围的末尾可以从范围的开始到达。到目前为止,标准库还没有将 noexcept
放在有前提条件的函数上(至少,一般情况下没有;可能有特殊情况),因为调试实现可以断言存在问题,例如,通过抛出异常: 当未定义的行为被触发时会发生什么是未定义的,如果他们愿意的话,实现可以自由定义任何一个。
此外,std::accumulate()
调用的任何函数都允许抛出异常,即任何 noexcept
声明都需要有条件。我认为算法一般不太可能获得相应的 noexcept
声明。
由于规范没有提到在合约中调用时 std::accumulate()
抛出的任何情况,如果被调用操作的 none 抛出则不会抛出。
std::accumulate
的 c++ 参考没有提到 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
必须执行的所有操作都可以抛出。
但即使除此之外,如果标准库函数没有非抛出异常规范并且函数的描述没有另外说明,则标准确实允许实现抛出实现定义的异常,请参阅[res.on.exception.handling]/4.
也就是说,如果在您的示例中使用 std::accumulate
会抛出异常,我会感到惊讶。不需要动态分配,因此不需要潜在的 std::bad_alloc
抛出,这是实现定义的异常最有可能的候选者。 int
上的求和、复制 and/or 移动操作也不会抛出。
在任何情况下,如果函数内部抛出异常,将 noexcept
添加到函数中不会导致未定义的行为。相反,明确定义的是,如果异常到达 noexcept
函数的外部范围,将调用 std::terminate
,默认情况下会中止程序,但可以在某种程度上进行自定义。
std::accumulate()
有先决条件,例如,范围的末尾可以从范围的开始到达。到目前为止,标准库还没有将 noexcept
放在有前提条件的函数上(至少,一般情况下没有;可能有特殊情况),因为调试实现可以断言存在问题,例如,通过抛出异常: 当未定义的行为被触发时会发生什么是未定义的,如果他们愿意的话,实现可以自由定义任何一个。
此外,std::accumulate()
调用的任何函数都允许抛出异常,即任何 noexcept
声明都需要有条件。我认为算法一般不太可能获得相应的 noexcept
声明。
由于规范没有提到在合约中调用时 std::accumulate()
抛出的任何情况,如果被调用操作的 none 抛出则不会抛出。