C++1x的应用总结之一移动捕获
在应用的工程中看到了如下的代码,以前还真没这么用过:
auto&& task = [e = std::move(ptr)]() mutable {
processTransaction(std::move(e));
查了下资料,在C++11中,对移动对象(如std::unique_ptr或std::future)放入到闭包里(就简单理解成lambda表达式),而实际情况经常有一个对象拷贝的代价比较高,但是移动的代码很小。这事儿在以前就比较麻烦了,不过C++14里做了一个十分巧妙的方式来解决了这种情况,即上面的代码的那种情况。
分析一下:
这个e代表是闭包里的变量,编译器看到这种声明会自动在闭包内声明这个auto e,类型是自动推导出来的。所以大家不要以为C++也可以不做强类型声明了。明白了这一点,估计其它就不用说了。
其实下面这种方式更容易让初接触的头大:
int a = 0;
int get(inta){return a+1;}
int main(void)
{
………….
[a = get(a)]()
{
cout << a << endl;
}();
……………….
}
但是一按上面的分析发现就非常简单了。两个小a不是一个变量,=号左面的是闭包内部自动声明的,由编译器来推导类型。后面的小a是捕获的外面的变量。
不过真正有意义的应该还是最上面介绍的在移动时的意义。
如果在C++11中不能使用这种特性,事情也就比较不好办了,但是可以类似于函数指针和std::function来写,或者说用bind来实现。
多说一句,看Lambda表达式(C++11 起)的说明:
构造一个闭包:能够捕获作用域中变量的无名函数。
语法
[ capture-list] ( params ) mutable(可选) constexpr(可选)(C++17) exception attribute -> ret { body } (1)
[ capture-list ] ( params ) ->ret { body } (2)
[ capture-list] ( params ) { body } (3)
[ capture-list] { body } (4)
看上面给的例程:
struct X {
int x, y;
int operator()(int);
void f()
{
// 下列lambda的语境是成员函数X::f
[=]()->int
{
return operator()(this->x + y);// X::operator()(this->x + (*this).y)
//this拥有类型X*
};
}
};
和这个:
int&(*fpi)(int*) = [](auto* a)->auto& { return *a; }; // ok
这两个例程出自:
http://zh.cppreference.com/w/cpp/language/lambda
新技术和新思想层出不穷啊,有点儿力拙的表现。