我发现 C++0x 闭包的使用令人困惑。我的初始report https://stackoverflow.com/questions/5543169/how-to-make-a-vector-of-functors-lambdas-or-closures-in-cox/5556376#5556376,以及后续一个 https://stackoverflow.com/questions/5556183/make-c-crash-without-casting/5557843#5557843,产生的混乱多于解释。下面我将向您展示麻烦的示例,希望找出代码中存在未定义行为的原因。所有代码片段都通过了 gcc 4.6.0 编译器,没有任何警告。
方案 1:有效
#include <iostream>
int main(){
auto accumulator = [](int x) {
return [=](int y) -> int {
return x+y;
};
};
auto ac=accumulator(1);
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
}
输出结果满足预期:
2 2 2
2 2 2
2 2 2
2. 方案 2:关闭,运行良好
#include <iostream>
int main(){
auto accumulator = [](int x) {
return [&](int y) -> int {
return x+=y;
};
};
auto ac=accumulator(1);
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
}
输出是:
4 3 2
7 6 5
10 9 8
程序 3:带有 std::function 的程序 1,工作正常
#include <iostream>
#include <functional> // std::function
int main(){
typedef std::function<int(int)> fint2int_type;
typedef std::function<fint2int_type(int)> parent_lambda_type;
parent_lambda_type accumulator = [](int x) -> fint2int_type{
return [=](int y) -> int {
return x+y;
};
};
fint2int_type ac=accumulator(1);
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
}
输出是:
2 2 2
2 2 2
2 2 2
程序 4:带有 std::function 的程序 2,未定义行为
#include <iostream>
#include <functional> // std::function
int main(){
typedef std::function<int(int)> fint2int_type;
typedef std::function<fint2int_type(int)> parent_lambda_type;
parent_lambda_type accumulator = [](int x) -> fint2int_type{
return [&](int y) -> int {
return x+=y;
};
};
fint2int_type ac=accumulator(1);
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
std::cout << ac(1) << " " << ac(1) << " " << ac(1) << " " << std::endl;
}
程序的第一次运行给出:
4 3 2
4 3 2
12364812 12364811 12364810
第二次运行同一程序:
4 3 2
4 3 2
1666060 1666059 1666058
第三个:
4 3 2
4 3 2
2182156 2182155 2182154
我对 std::function 的使用如何破坏代码?为什么程序 1 - 3 运行良好,而程序 4 在调用 ac(1) 三次(!)时正确?为什么程序 4 在接下来的三种情况下陷入困境,就好像变量 x 是通过值而不是引用捕获的一样。 ac(1) 的最后三个调用是完全不可预测的,就好像对 x 的任何引用都会丢失一样。