c++11新特性篇-lambda表达式

Lambda 表达式是C++11引入的新特性。Lambda 表达式允许你在代码中创建匿名函数(或闭包),而不需要单独定义函数。它提供了一种更简洁和方便的方式来编写可调用对象,并且可以捕获外部变量,使得在函数对象中可以使用外部作用域的变量。

1. 基本语法

Lambda 表达式的基本语法如下:

[capture](params) opt -> ret {body;};


- capture:捕获列表,用于捕获外部变量,可以是值捕获、引用捕获或混合捕获。
- params:参数列表,与普通函数的参数类似。
- ret:返回类型,用 `->` 指定,可以省略,编译器会自动推导返回类型。
- body:函数体内的代码。

Lambda 表达式的引入使得C++程序员能够更加方便地编写高阶函数、在算法中使用自定义操作,以及在多线程编程中处理并发操作。Lambda 表达式大大提高了C++语言的表达能力和灵活性。

2. 捕获列表

2.1 值捕获

捕获外部变量的值,Lambda函数内部无法修改该变量

int x = 42;
  auto lambda = [x]() {
      std::cout << "Captured value: " << x << std::endl;
  };

2.2 引用捕获

捕获外部变量的引用,Lambda函数内部可以修改该变量

 int y = 42;
  auto lambda = [&y]() {
      y++;
      std::cout << "Modified reference: " << y << std::endl;
  };

2.3 隐式捕获

 使用 `=` 捕获外部作用域的所有变量(值捕获),或使用 `&` 捕获所有变量的引用

 int a = 1, b = 2;
  auto lambda1 = [=]() {
      std::cout << "Captured value a: " << a << std::endl;
      std::cout << "Captured value b: " << b << std::endl;
  };

  auto lambda2 = [&]() {
      a++;
      b++;
      std::cout << "Modified reference a: " << a << std::endl;
      std::cout << "Modified reference b: " << b << std::endl;
  };

在捕获列表中,你可以混合使用值捕获、引用捕获和隐式捕获,以适应不同的需求。捕获列表提供了灵活的机制,使得Lambda函数能够访问并操作外部作用域的变量。

还有几种不太常用的捕获方式, 了解下格式即可:

[=, &foo] - 按值捕获外部作用域中所有变量, 并按照引用捕获外部变量 foo

[this] - 捕获当前类中的this指针
        让lambda表达式拥有和当前类成员函数同样的访问权限
        如果已经使用了 & 或者 =, 默认添加此选项

3. 函数本质

Lambda 函数(Lambda expression)是C++中一种匿名函数的表示方式。它允许你在代码中创建简单的函数,而无需像传统函数那样单独定义一个函数名。Lambda 函数的本质实际上是一个可调用的对象,或者说是一个函数对象(function object)。

Lambda 函数背后的实现原理主要涉及以下几个关键概念:

3.1 闭包(Closure)

Lambda 函数可以捕获外部作用域的变量,形成闭包。捕获的变量被保存在Lambda函数内部,使得Lambda函数可以在其定义的作用域外部访问这些变量。Lambda 函数通过闭包实现了对外部变量的访问。

3.2  仿函数(Functor)

Lambda 函数实际上是一个函数对象,类似于传统的仿函数,可以像函数一样被调用。Lambda 函数在内部重载了函数调用运算符 operator(),使得它可以像函数一样被调用。

3.3  编译器生成的匿名类

在编译时,C++编译器会为Lambda 函数生成一个匿名类,并在其中实现Lambda 函数的功能。这个类内部包含捕获的变量,并提供了函数调用运算符的重载,使得Lambda 函数可以被调用。

Lambda 函数的本质可以看作是一个带有函数调用运算符重载的匿名类对象,这个对象包含了Lambda 函数的行为定义以及捕获的外部变量。Lambda 函数的简洁语法和灵活性使得它成为C++中一个强大的编程工具,特别适用于简单的、局部性的操作。

4. 应用

Lambda 表达式在C++中有许多应用场景,主要体现在以下几个方面:

4.1  STL 算法

Lambda 表达式可以用作STL(Standard Template Library)算法的谓词(predicate),即用于定义元素的比较、筛选、变换等操作。它使得使用STL算法更加灵活。

   std::vector<int> numbers = {1, 2, 3, 4, 5};
   // 使用 Lambda 表达式对容器中的元素进行平方操作
   std::transform(numbers.begin(), numbers.end(), numbers.begin(), [](int x) { return x * x; });

4.2 函数对象

Lambda 表达式可以替代传统的函数对象(Functor)或者函数指针,用于自定义排序、查找等操作。Lambda 表达式在这种情况下可以减少代码的冗余,提高可读性。

  std::sort(numbers.begin(), numbers.end(), [](int a, int b) { return a > b; });

4.3 事件处理和回调函数

在事件驱动的程序中,Lambda 表达式可以作为回调函数,用于处理事件

   button.onClick([]() { std::cout << "Button clicked!" << std::endl; });

4.4 多线程编程

Lambda 表达式在多线程编程中非常有用,可以方便地将任务传递给线程,简化了多线程编程的代码。

   std::thread t1([]() { std::cout << "Thread 1" << std::endl; });
   std::thread t2([]() { std::cout << "Thread 2" << std::endl; });
   t1.join();
   t2.join();

4.5 智能指针和资源管理

在使用智能指针时,Lambda 表达式可以用于自定义删除器,用于在指针释放时执行特定的操作。

   std::shared_ptr<int> ptr(new int, [](int* p) { std::cout << "Deleting pointer..." << std::endl; delete p; });

这些只是 Lambda 表达式的一些基本应用场景,实际上,在C++的各种编程场景中,Lambda 表达式都可以大显身手,使得代码更加简洁和灵活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值