Eva*_*per 8 c++ lambda pass-by-value visual-c++ c++11
我有一个Visual Studio 2010 C++程序,其主要功能是:
vector<double> v(10);
double start = 0.0; double increment = 10.0;
auto f = [&start, increment]() { return start += increment; };
generate(v.begin(), v.end(), f);
for(auto it = v.cbegin(); it != v.cend(); ++it) { cout << *it << ", "; }
cout << endl << "Changing vars to try again..." << endl;
start = 15; increment = -1.5;
generate(v.begin(), v.end(), f);
for(auto it = v.cbegin(); it != v.cend(); ++it) { cout << *it << ", "; }
return 0;
Run Code Online (Sandbox Code Playgroud)
当我在MS Visual Studio中编译它时,第一个生成符合我的预期,产生"10,20,... 100".第二个没有; lambda"看到"变化start而不是变化increment,所以我得到"25,35,...... 115".
当声明表达式而不是调用表达式时,Visual C++编译器将lambda表达式绑定到其捕获的变量.... [T]他稍后在程序中重新分配[由值捕获的变量]不会影响表达式的结果.
所以我的问题是:这是符合标准的C++ 11行为,还是微软自己的古怪实现?额外奖励:如果是标准行为,为什么标准是这样编写的?是否与强制执行函数式编程的参照透明度有关?
seh*_*ehe 16
使用lambda表达式,在声明时捕获绑定变量.
此示例将非常清楚:https://ideone.com/Ly38P
std::function<int()> dowork()
{
int answer = 42;
auto lambda = [answer] () { return answer; };
// can do what we want
answer = 666;
return lambda;
}
int main()
{
auto ll = dowork();
return ll(); // 42
}
Run Code Online (Sandbox Code Playgroud)
很明显,捕获必须在调用之前发生,因为捕获的变量在以后不再存在(不在范围内,也不在生命周期内).
它在创作时受到约束.考虑:
#include <functional>
#include <iostream>
std::function<int(int)> foo;
void sub()
{
int a = 42;
foo = [a](int x) -> int { return x + a; };
}
int main()
{
sub();
int abc = 54;
abc = foo(abc); // Note a no longer exists here... but it was captured by
// value, so the caller shouldn't have to care here...
std::cout << abc; //96
}
Run Code Online (Sandbox Code Playgroud)
a调用函数时没有- 编译器无法返回并更新它.如果您通过a引用传递,那么您有未定义的行为.但是,如果你通过价值任何合理的程序员会期望这是有效的.