你学会lambda表达式了吗???

lambda表达式

一个lambda表达式具有一个返回类型,一个参数列表和一个函数体;和函数不同,lambda定义在函数内部

表达式形式:

    [capture list](parameter list)->return type{ function body}
    //捕获列表      参数列表          返回类型       函数体

可以忽略参数列表和返回类型,但是必须永远包含捕获列表和函数体

(这种返回类型及叫做尾置返回:真正的返回类型在形参列表后面)

eg:

    auto f = [ ]{return 5; };       //此处省略参数列表等价于指定一个空参数列表。省略返回类型auto可以自动推断
    cout << f() << endl;     //调用方式与普通函数的调用方式一样

一,向lambda传递参数

  • 需要保证实参与形参的数目相同
  • lambda表达式不能有默认参数(这个地方我也没搞懂为什么,可能就是规定,或者与函数模板有关)

vector a = { 1, 2, 3, 4, 5, 6 };
    auto f = [](vectorconst a){return *a.begin(); };             //传递的参数为:vectorconst a
    cout << f(a) << endl;

空捕获列表表示不使用它所在函数的任何局部变量。

二,使用捕获列表

需要可以使用其局部变量,但是只能使用哪些明确指明的变量,一个lambda通过将局部变量包含在其捕获列表中来指出将会使用这些变量。

    int aa = 10;
    auto x = [aa](int b){return aa > b ? aa : b; };

eg:

#include
#include
#include
#include
using namespace std;

void elimDups(vector &world)    //删除重复元素
{
	sort(world.begin(), world.end());    //按字典序排序
	auto do_unique = unique(world.begin(), world.end());       
	//使得每一个元素只出现一次,此时do_unique返回不重复区域的后一个位置
	//unique并没有删除元素,而是覆盖了,他后面的元素仍然存在,但是我们不知道它的值是什么
	for (auto &m : world){
		cout << m <<"  ";
	}
	cout << endl;
	world.erase(do_unique, world.end());
	//从开始重复的第一个元素,删除到最后
	for (auto &m : world){
		cout << m << "  ";
	}
	cout << endl;
}
int main()
{
	vector worlds = { "the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle" };
	elimDups(worlds);    //删除重复元素

	stable_sort(worlds.begin(), worlds.end(), 
		[](const string &a, const string &b){return a.size() < b.size(); });     //按长度排序
	for (auto &m : worlds){
		cout << m << "  ";
	}
	cout << endl;

	int sz = 4;
	auto world = find_if(worlds.begin(), worlds.end(),           //获取一个迭代器,指向第一个满足size()>sz的
		[sz](const string &a){return a.size() >= sz; });
	
	auto num = worlds.end() - world;    //满足size()>sz的长度

	for_each(world, worlds.end(), [](const string &s){cout << s << "  "; });     //打印满足的部分

	system("pause");
	return 0;
}

三,lambda捕获和返回

  • 值捕获

与传值参数类似,采用值捕获的前提是变量可以拷贝。与参数不同,被捕获的变量在创建时拷贝。
因此随后对其的修改不会影响到lambda内对应的值

int a = 10;
 auto f = [a]{return a; };

  • 引用捕获

引用捕获必须保证lambda在执行时被引用的对象是存在的。

int a = 10;
    auto f = [&a]{return a; };

  • 隐式捕获

除了显示列出我们希望使用的来自所在函数的变量之外,还可以让lambda体中的代码来推断我们要使用哪些变量。为了指示编译器推断捕获列表,应在捕获列表中写一个&或=。&告诉编译器采用引用捕获方式,=则采用值捕获方式。

注意:

当混合使用隐式捕获和显示捕获时,捕获列表中第一个元素必须是一个“&”或“=”,此符号指定了默认捕获方式为引用或值。

当混合使用隐式捕获和显示捕获时,显示捕获必须使用与隐式捕获不同的方式。

#include
using namespace std;

int main()
{
	int a = 10;
	int b = 20;
	auto f = [&, b]{return a > b ? a : b; };

	auto ff = [=, &b]{return a < b ? a : b; };
	
	cout << f() << endl;
	cout << ff() << endl;
	system("pause");
	return 0;
}

四,可变lambda

默认情况下对于值被拷贝的变量,lambda不会改变其值。如果我们希望改变被捕获的值,则在参数裂变首加上mutable。

    int a = 10;
    //auto f = [a](){return ++a; };    错误,a不能被修改
    auto f = [a]()mutable{return ++a; };   

一个引用捕获的变量是否能修改,依赖于指向的是一个const类型还是非const类型

五,指定lambda返回类型

即使用尾置返回类型:

    transform(a.begin(), a.end(), a.begin(),
        [](int i)->int{if (i < 0) return -i; else return i; });

 

网上搜的一段话:

lambda本质是模板,参数声明为auto借助了模板的推断机制。

auto func = [] (auto x, auto y) {
    return x + y;
};
// 上述的lambda相当于如下类的对象
class X {
public:
    template
    auto operator() (T1 x, T2 y) const { // auto借助了T1和T2的推断
        return x + y;
    }
};

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(C/C++学习,c++,lambda)