我一直在努力反对那个正在危及我的一个项目的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 ::函数未指定为警告.