C++11 lambda表达式

[capture](parameters) mutable ->return-type{statement} 

捕获列表与函数比必须存在   -> 可省略 如果无参数  参数列表连同括号可省略


#include "pch.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

void insert(vector<string>& word) {
	word.push_back("the");
	word.push_back("quick");
	word.push_back("red");
	word.push_back("fox");
	word.push_back("jumps");
	word.push_back("over");
	word.push_back("the");
	word.push_back("slow");
	word.push_back("red");
	word.push_back("turtle");
}
void print(vector<string> w) {
	for (auto i : w)
		cout << i << " ";
	cout << endl;
}
void bigges(vector<string> word, vector<string>::size_type sz) {
	cout << "原序列: " << endl;
	print(word);
	cout << "字典序升序:" << endl;
	sort(word.begin(), word.end(),
		[](const string& w1, const string& w2) { return w1 < w2; }
	);
	print(word);
	cout << "去重: " << endl;
	auto iter = unique(word.begin(), word.end());
	word.erase(iter, word.end());
	print(word);
	cout << "原序列不变 按长度递增: " << endl;
	stable_sort(word.begin(), word.end(),
		[](const string& w1, const string& w2) { return w1.size() < w2.size(); }
	);
	print(word);
	cout << "第一个大于等于" << sz << "的元素" << endl;
	auto it = find_if(word.begin(),word.end(),
		[sz](const string& w) {return w.size() >= sz; }
	);
	cout << "下标: " << it-word.begin() << endl;
	cout << "值: " << *it << endl;

	cout << "从it开始用->链接:" << endl;
	for_each(it, word.end(), [](string w) {
		cout << w << "->";
	});
}



int main()
{

	vector<string> word;
	insert(word);

	//完整的bigges
	bigges(word, 4);
	return 0;
}

 创建lambda并返回对象时 要在结尾 }  后加分号

 

三种捕获方式:

值捕获

一定注意:是创建时候拷贝 而不是调用的时候拷贝 

程序举栗☟☟☟

int main()
{
	int x = 99;
	auto f = [x](int y) {
		cout << x + y << endl;
	};
	x++;  //x = 100
	f(1);
	return 0;
}

 

 下面改一下程序:
 

int main()
{
	int x = 99;
	x++;  //x = 100
	auto f = [x](int y) {
		cout << x + y << endl;
	};
	f(1);
	return 0;
}

 

可见 第一个程序中  x初始化是99  然后紧接着就创建了lambda  那么捕获到的x永远都是99  不论后面x值怎么变化,这就是所谓的创建时初始化

值捕获 在函数体中试图修改捕获变量是非法的 

 

如果需求需要改变值捕获的局部变量值  在参数列表后加mutable关键字

int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	//隐式值捕获
	auto f1 = [a]() mutable{
		a++;
		return a;
	};
	cout << f1() << endl;
	cout << a << " " << b << " " << c << endl;
	return 0;
}

但是这种方式只在内部改变 或者说改变捕获变量的副本

 

引用捕获

与值捕获相对应,在调用时初始化

int main()
{
	int x = 99;

	auto f1 = [&x]() {
		x++;
		return (x + 1);
	};
	x++;  //x = 100
	cout << f1() << endl;
	cout << "x = " << x << endl;
	return 0;
}

在lamdba中修改捕获的变量 相当于修改外部的变量 因为是引用绑定

注:必须保证引用的对象在lambda执行时是存在的。

        IO流必须是引用捕获

 

隐式捕获

int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	//隐式值捕获
	auto f1 = [=]() mutable{
		a++;
		b++;
		c++;
		return a + b + c;
	};
	cout << f1() << endl;
	cout << a << " " << b << " " << c << endl;
	return 0;
}

 

 

int main()
{
	int a = 1;
	int b = 2;
	int c = 3;
	//隐式值捕获
	auto f1 = [=, &a]() mutable{
		a++;
		b++;
		c++;
		return a + b + c;
	};
	cout << f1() << endl;
	cout << a << " " << b << " " << c << endl;
	return 0;
}

 

 

隐式捕获就是捕获lmabda定义之前的所有变量 

混合隐式捕获:

[&, identifie_list]

[= , identifie_list]

开头必须是值隐式或者引用隐式   如果开头是值隐式捕获,后面给出引用显式捕获列表   反之如此

注意 逗号后必须有个空格

 

附上C++14新规定:

Lambda函数

在C++11中,lambda函数参数需要被声明为具体的类型。C++14放宽了这一要求,允许lambda函数参数类型使用类型说明符auto。

auto lambda = [] (auto x, auto y) {return (x + y); }

尽管使用了C++11的关键字auto,泛型Lambda函数并不遵循auto类型推导的句法,而是遵循模板参数推导的规则(它们相似,但并不是在所有情况下都是相同的)。以上代码与下面的等价:

struct unnamed_lambda

{

template <typename T,typename U>

auto operator()(T x, U y) const

{

return (x+y);

}

};

auto lambda = unnamed_lambda();

Lambda函数

C++11的lambda函数通过值拷贝或引用捕获在外层作用域声明的变量。这意味着lambda的值成员不可以是只能move的类型。 C++14允许被捕获的成员用任意的表达式初始化。这既允许了通过move捕获,也允许了任意声明lambda的成员,而不需要外层作用域有一个具有相应名字的变量。

这是通过使用一个初始化表达式完成的:

auto lambda=[value{1}] { return value; }

lambda函数 lambda 会返回1,因为value被初始化为1。被声明的捕获变量的类型以与auto相同的方式,根据初始化表达式推断。

使用标准函数std::move可以使之被用以通过move捕获:

auto ptr=std::make_unique<int>(10);//See below for std::make_unique

auto lambda=[ptr{std::move(ptr)}] { return(*ptr); }

声明ptr{std::move(ptr)}使用了两次ptr。第一次使用声明了一个新的变量,但由C++的作用域规则,在初始化表达式求值完毕之前,该变量不在作用域内。所以第二个ptr表示之前在lambda之外声明的变量。

返回类型函数

C++11允许lambda函数根据return语句的表达式类型推断返回类型。C++14为所有的函数提供了这个能力。C++14还拓展了原有的规则,使得函数体并不是return expression;形式的函数也可以使用返回类型推导。

为了诱发返回类型推导,函数声明必须将auto作为返回类型,但没有C++11的后置返回类型说明符:

auto DeduceReturnType(); //Return type to be determined.

如果函数实现中含有多个return表达式,这些表达式必须可以推断为相同的类型。

使用返回类型推导的函数可以被前向声明,但在定义之前不可以使用。它们的定义在使用它们的翻译单元之中必须是可用的。

这样的函数中可以存在递归,但递归调用必须在函数定义中的至少一个return语句之后,例如:

auto Correct(int i)

{

if (i == 1)

return (i); // return type deduced as int

else

return (Correct(i-1)+i); // OK to call it now

}

但是下面这样写是错误的:

auto Wrong(int i)

{

if(i!=1)

return (Wrong(i - 1) + i); // Too soon to call this. No prior return statement.

else

return i; // return type deduced as int

}

 

对我画红的语句解释一下:

C++14 扩展了

1.如果函数体中有return之外的语句  也可以自动推导返回类型  可以不使用尾置返回类型

2.如果函数体有多个return 语句  则下一个必须与上一个返回类型相同

3.在捕获列表中可以临时自定义   变量名{变量值}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值