[英]Iterator increment leading to different results in clang and gcc
I encountered a weird issue in the following code snippet, leading to different results.我在以下代码片段中遇到了一个奇怪的问题,导致了不同的结果。
Apple clang (tested with 3.8.0 and 11.0) returns the expected value 10 but gcc (tested with 5.4.0 and 9) returns 12. Apple clang(用 3.8.0 和 11.0 测试)返回预期值 10,但 gcc(用 5.4.0 和 9 测试)返回 12。
#include <functional>
#include <iostream>
#include <vector>
int acc(std::function<int(int, int)> func, std::vector<int> operands) {
auto it = operands.begin();
int result = func(*it, *(++it)); // <-- causing issue, ++it not working as expected
if (operands.size() > 2) {
for (++it; it!=operands.end(); ++it) {
result = func(result, *it);
}
}
return result;
}
int main() {
std::cout << acc([](int a, int b){ return a+b; }, {3, 5, 2}) << std::endl;
}
It can be reproduced for example, using rextester.com .例如,可以使用rextester.com复制它。
While debugging I found out that the iterator increment ++it
seems to be the problem.在调试时我发现迭代器增量++it
似乎是问题所在。 Replacing it by it+1
followed by a it = it + 1
statement leads to the expected result in both compilers.用it+1
后跟it = it + 1
语句替换它会导致两个编译器中的预期结果。 But why is that handled differently among the compilers?但是为什么编译器之间的处理方式不同呢?
But why is that handled differently among the compilers?但是为什么编译器之间的处理方式不同呢?
Because before C++17, it was unspecified in what order function arguments are evaluated.因为在 C++17 之前,未指定以什么顺序评估 function arguments。
I would suggest not calling func
in the initialisation of result
.我建议不要在result
的初始化中调用func
。
int acc(std::function<int(int, int)> func, std::vector<int> operands) {
if (operands.empty()) throw std::out_of_range();
auto it = operands.begin();
int result = *it;
for (++it; it!=operands.end(); ++it) {
result = func(result, *it);
}
return result;
}
Note that std::function
is often overkill for passing functions.请注意, std::function
对于传递函数通常是矫枉过正的。 The standard library prefers templated higher-order functions, eg copying std::accumulate
标准库更喜欢模板化的高阶函数,例如复制std::accumulate
template<class BinaryOperation >
int acc(BinaryOperation op, std::vector<int> operands)
Where BinaryOperation
is any function-like type that is callable as int(int, int)
, such as your lambda's type其中BinaryOperation
是可调用为int(int, int)
的任何类似函数的类型,例如您的 lambda 类型
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.