我看到在 C++ 14 特性中支持 Lambda 表达式捕获 move-only 的类型(原先是引用或值传递),于是写了一个小 demo:
auto p = std::make_unique<int>(1);
auto task1 = [p = move(p)](){ *p = 5; };
cout << *p << endl;
上述代码可以通过编译,但是运行时出现 core dump ,明显是因为此时 p 已经被 move 到 Lambda 表达式中去了,这里就迷惑,我一直以为要 auto task = [](){...}(); 或是 task1(); 执行时才会做参数的初始化(类似函数那样),但从结果来看,从声明的那一刻变量就已经被捕获了。
虽然这一点对原本的值传递和引用捕获的参数来讲没有什么感知,但是对于捕获 move-only 类型的函数确实会产生一定的影响,因为从 Lambda 声明的这一刻开始你原本的外部变量就不能使用了。
另外被捕获到 Lambda 内部的 move-only 变量是以类似 static 的状态存在的,即多次调用 task 对 *p 的改变会累积,以这个 demo 可以看的比较清楚:
auto p = std::make_unique<int>(1);
auto task1 = [p = move(p)](){
(*p)++;
cout << *p << endl;
};
task1();
task1();
task1();