c – 奇怪的未定义的行为与棘手的lambda表达式

前端之家收集整理的这篇文章主要介绍了c – 奇怪的未定义的行为与棘手的lambda表达式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在努力反对那个正在危及我的一个项目的lambda表达式的问题.我找到了一个解决方案,但是我想要明确地了解它是如何和为什么它的工作,如果它是可靠的.
#include <iostream>
#include <functional>
#include <unordered_map>

typedef std::function<const int&(const int&)> Callback;

int f(int i,Callback callback) {
    if (i <= 2) return 1;
    return callback(i-1) + callback(i-2);
}

int main(void) {

    std::unordered_map<int,int> values;

    Callback callback = [&](const int& i) {
        if (values.find(i) == values.end()) {
            int v = f(i,callback);
            values.emplace(i,v);
        }
        return values.at(i);
    };

    std::cout << f(20,callback) << std::endl;

    return 0;

}

我知道这是计算第20个斐波纳契数字的疯狂方法,但它是我能够阐述的最紧凑的SSCCE.

如果我用g -O0编译上面的代码,我执行程序,我得到6765,这实际上是第20个斐波那契数.如果我用-O1,-O2或-O3编译,我得到262144,这是垃圾.

如果我使用Valgrind配置程序(用-O0 -g编译),我得到条件跳转或移动取决于行std :: cout上的未初始化值(<<< f(20,回调)<<的std :: ENDL;但堆栈跟踪没有说什么有用. 我不知道为什么我这样做最终:

Callback callback = [&](const int& i) -> const int& {

通过这个小小的修改,一切都可以按预期的方式进行任何优化级别的编译,而Valgrind报告没有问题.

你能帮我了解发生了什么吗?

解决方法

没有 – > const int& lambda的返回类型是int.由于Callback的返回类型是const int& amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp; amp;未定义的行为.

对于这个简单的例子,容易的修复是根本不使用引用(Example at Coliru),但是我假设你的真正的代码是处理比int更重的对象.不幸的是,当您分配一个返回非引用的函数返回类型为引用的std ::函数时,std ::函数未指定为警告.

猜你在找的C&C++相关文章