我一直在努力解决一个危害我的项目的 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
),我会上Conditional jump or move depends on uninitialised value(s)
线std::cout << f(20, callback) << std::endl;
,但堆栈跟踪并没有说明任何有用的信息。
我不知道为什么我最终得到了这个:
Callback callback = [&](const int& i) -> const int& {
通过这个小小的修改,任何优化级别的编译都可以按预期进行,并且 Valgrind 没有报告任何问题。
你能帮我理解发生了什么吗?