跳至主要內容

lambda表达式

张威大约 3 分钟c/c++lambda

lambda表达式

  • C++11 函数对象的升级版 =》 lambda表达式
  • 函数对象的缺点:需要定义一个类
  • 函数对象使用在 泛型算法参数传递 比较性质/自定义操作 优先级队列 智能指针(自定义智能指针的删除器)

lambda表达式原理: 就是函数对象更高级的实现!

1、lambda表达式语法

[捕获外部变量](形参列表)->返回值{操作代码}
如果lambda表达式的返回值不需要,那么"->返回值"可以省略
    
[捕获外部变量]
[]:表示不捕获任何外部变量
[=]:以传值的方式捕获外部的所有变量
[&]:以传引用的方式捕获外部的所有变量
[this]:捕获外部的this指针
[=,&a]:以传值的方式捕获外部的所有变量,但是a变量以传引用的方式捕获
[a, b]:以值传递的方式捕获外部变量a和b
[a, &b]:a以值传递捕获,b以传引用的方式捕获

示例

lambda表达式对应函数对象小括号重载函数的

template<typename T = void>//用不到参数直接写void
class TestLambda {
public:
	TestLambda01() {}
	void operetor()() {
		cout << "hello world!" << endl;
	}
};

int main() {
    auto func1 = []()->void {cout << "hello world!" << endl;};
    func1();
    
    TestLambda01<> t1;	
    t1();
    return 0;
}
  • []为空,
  • ()是运算符重载函数,具体接收的参数的个数
  • 然后是返回值,看是无类型还是其他类型。
  • 最后是函数代码
template<typename T = int>
class TestLambda03 {
public:
    TestLambda03(int a, int b)
        : ma(a), mb(b) {}
    void operator()(int a, int b) const {
        int tmp = ma;
        ma = mb;
        mb =tmp;
    }
    
private:
    int ma;
    int mb;
}

auto func3 = [a, b]() {
    int tmp = a;
    a = b;
    b = tmp;
}
  • []不为空,
template<typename T = int>
class TestLambda02 {
public:
    TestLambda02() {}
    int operator()(int a, int b) const {
        return a + b;
    }
}

auto func2 = [](int a, int b)->int { return a + b;};
cout << func2(20, 30) << endl;

TestLambda02<> t2;
cout << t2(20, 30) << endl;

值传递

加上mutable表示将的形参a,b改掉;

int a = 10;
int b = 20;
auto func3 = [a, b]() mutable {
    int tmp = a;
    a = b;
    b = tmp;
};

引用传递

修改的是实参,不需要加mutable

int a = 10;
int b = 20;
auto func3 = [&a, &b]() {
    int tmp = a;
    a = b;
    b =tmp;
};

lambda应用

例1—从大到小排序

for(int i = 0; i < 20; ++i) {
	vec.push_back(rand() % 100 + 1);
}

sort(vec.begin(), vec.end(), [](int a, int b)->bool {
    return a >b;});

for(int val : vec) {
    cout << val << " ";
}
cout << endl;

例2—按序插入元素65

auto it = find_if(vec.begin(), vec.end(), [](int a)->bool{ return a < 65;});
if(it != vec.end()) {
	vec.insert(it, 65);
}

for(int val : vec) {
	cout << val << " ";
}
cout << endl;

for_each

for_each(vec.begin(), vec.end(), [](int a) {
	if(a % 2 == 0) {
		cout << a << " ";
	}
});
cout << endl;

lambda表达式的应用实践

既然lambda表达式只能使用在语句当中,如果想跨语句使用之前定义好的lambda表达式,怎么办?用什么类型来表示lambda表达式?

  • lambda表达式 =》 函数对象 用function类型绑定它
  • 用function类型表示函数对象的类型
  • bind绑定器绑定的结果依然还是一个函数对象;

1、计算器案例

2、智能指针案例

3、优先级队列

上面写法灵活性太差。现在优化:

priority_queue本身就有3个模板参数,分别是元素类型、容器类型、函数对象

可以接收外部自定义的函数对象

#include <iostream>
#include <functional>
#include <queue>
using namespace std;


class Data
{
public:
	Data(int val1 = 10, int val2 = 10) :ma(val1), mb(val2) {}
	int ma;
	int mb;
};
int main()
{
	//优先级队列
	//priority_queue<Data> queue;
	using FUNC = function<bool(Data&, Data&)>;
	priority_queue<Data, vector<Data>, FUNC>
		maxHeap([](Data& d1, Data& d2)->bool
			{
				return d1.mb > d2.mb;
			});
	maxHeap.push(Data(10, 20));
	maxHeap.push(Data(15, 15));
	maxHeap.push(Data(20, 10));

	return 0;
}