简体   繁体   English

迭代器增量导致 clang 和 gcc 中的不同结果

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

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