lambda表达式
lambda表达式是可调用对象的一种,在c++中可调用对象有以下几种:
1,函数和函数指针
2,重载了‘()’运算符的类,以及lambda表达式
从实现上来将,函数指针和函数都是等价于一段代码的执行地址,lambda表达式其实就是一个匿名的重载了'()'运算符的对象
lambda表达式的用法
[capture list] (parameter list) -> return type { function body }
lambda常常作为可调用的参数被传入某一个函数中。
需要注意的地方:
1)在不指定返回类型时,如果函数体只有一个return语句,则会推断正确的返回类型,否则一律为void
2)lambda表达式的捕获可以为值捕获,也可以为引用捕获,捕获的时候需要使用&符号表示引用
3) 当lambda进行值捕获时,是在lambda被创建时进行拷贝,而不是在lambda被调用时,原因结合lambda的实现方式是显而易见的
4)在使用它所在函数的静态局部变量以及它所在函数之外声明的变量时,无须捕获,可以直接使用。这句话暂且可以理解成只有静态变量和全局变量都可以直接使用,因为我们如果写下面的代码,编译器是会报错的 - -!
void fun() { auto x = [xx] {cout << xx;}; //出错,xx不可见 x(); } int main(){ int xx = 3; //在fun函数体外声明的变量xx fun(); return 0; }
此处应该说在lambda定义时,直接定义在lambda所在函数之外的变量可以直接使用- -!
lambda表示通常用在懒得命名的时候,或者需要进行捕获的一些简单操作,如果要进行复杂操作,通常应该使用函数,可以使用
标准库中的bind函数来解决需要捕获的问题。
bind函数定义在头文件functional中
使用bind函数还需要使用定义在命名空间std::placeholders中的占位符,bind将返回一个可调用对象,bind的使用方式是这样的
auto g = bind(f, a, b, _2, c, _1); //其中f为可调用对象,_1表示调用g时,传入的第一个参数,_2依次类推,之后按照这个顺序将参数传进f。
g(x, y);
以上两句等价于:
f(a, b, y, c , x)
bind的实现原理很简单,接受可变参数列表,以及一个参数列表很长的可调用对象,然后生成一个lambda对象,捕获参数列表里非_1,_2...的参数,然后把占位符的参数作为lambda对象的参,就搞定了
值得注意的是,非占位符默认是以值传递的方式实现的(而占位符则按照可调用对象f指定的方式传递),比如
f(const string&, ostream&);
auto g = bind(f, _1, std::cout);
此时g("str")会出错,因为bind函数试图将不可以拷贝的cout对象,以值传递的方式拷贝至自动生成的lambda中。
如果要改变这次的传递方式,可以使用ref(),以及cref() // const 引用.. 函数,他们接受一个引用,返回一个可以拷贝的、包含给定的引用的对象。
至于ref(), cref()的实现在模板技术全部讲完之后就懂了,占坑
浙公网安备 33010602011771号