C++:函数指针进阶(三):Lambda函数详解(二):Lambda接收方式

Lambda表达式是C++11引入的新特性,允许在代码中直接定义匿名函数。它们常用于简洁地封装传递给算法或异步操作的代码块。Lambda的组成部分包括捕获列表、参数列表、可变规格、返回类型和函数体。Lambda可以按值或引用捕获外部变量,并且可以转换为函数指针或std::function对象。文章讨论了Lambda的语法、优缺点以及工作原理,并通过示例展示了其用法。
摘要由CSDN通过智能技术生成

一:Lambda表达式概述

  • Lambda表达式是现代C++在C++11和更高版本中的一个新语法糖,在C++11,C++14,C++17和C++20中Lambda表达的内容还在不断更新。
  • Lambda表达式(也称为lambda函数)是在调用或作为函数参数传递的位置处定义匿名函数对象的便捷方法。
  • 通常,lambda用于封装传递给算法或异步方法的几行代码。

二:lambda表达式示例

Lambda有很多种叫法,有Lambda表达式,Lambda函数,匿名函数,本文为了方便表述统一用Lambda表达式叙述。下面是一个Lambda表达式实例。

#include <algorithm>
#include <cmath>

void abssort(float* x, unsigned n) 
{

    std::sort(x,x+n),
       // Lambda expression begins
          [](float a, float b) {

                return  (std::abs(a)< std::abs(b));
          }
      // Lambda expression end
}
在上面的实例中,std::sort 函数第三个参数应该是传递一个 排序规则的函数,但是这个实例中直接将排序函数的 实现:写在了应该传递函数的位置,省去了定义排序函数的过程,对于这种不需要复用且短小的函数,直接传递函数体可以增加代码的可读性。

三:Lambda表达式语法定义

 

1:捕获列表:在C++规范中也称为Lambda导入器,捕获列表总是出现在lambda函数的开始处。实际上,[] 是lambda引出符,编译器根据该引出符判断接下来的代码是 lambda函数,捕获列表能够捕捉上下文的变量,以供Lambda函数使用。

2:参数列表:与普通函数的参数列表一致,如果不需要参数传递,则可以连同括号 “()” 一起省略

3:可变规格:mutable修饰符,默认情况下Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可以省略(即使参数为空)

4:异常说明:用于lambda表达式内部函数抛出的异常。

5:返回类型:lambda表达式的函数体返回类型我们可以在不需要返回值得时候可以连同 “->”一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。

说明:lambda表达式的返回类型会自动推导。除非指定了返回类型,否则不必使用关键字。返回类型类似于通常的方法或函数的返回类型部分。但是返回类型必须在参数列表之后,并且必须在返回类型 -> 之前包含类型关键字。如果lambda主体仅包含一个 return语句或者该表达式返回值,那么可以省略Lambda表达式的  return-type 部分,如果Lambda主体包含一个  return语句,则编译器 将从 return表达式的类型中推导出 return类型。否则: 编译器将返回类型推导为  void .

auto x = [ ](int i) {return i ;}

6:lambda函数体:与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

 四:Lambda表达式的优缺点

优点

  1. 可以直接在需要调用函数的位置定义短小精悍的函数,而不需要预先定义好函数
  2. 使用lambda表达式变得更加紧凑,结构层次更加明显,代码可读性好

例如:

std::find_if(v.begin(),v.end(),[](int& item) {return item >2} ) ;

缺点:

  • lambda表达式语法比较灵活,增加了阅读代码的难度
  • 对于函数复用无能为力 

五:lambda表达式工作原理

编译器会把一个Lambda表达式生成一个匿名类的  匿名对象,并在类中重载函数调用运算符,实现 operator()方法。

auto  print  = [] {cout <<  " hello world" << endl ;  }

编译器会把上述代码翻译为下面代码

class print_class 
{

public:
    void operator()(void) const {
        
         cout << "hello world"  << endl;
    }

};


// 用构造的类创建对象,print 此时就是 一个函数对象
auto print = print_class();

事实上,编译器这么翻译和仿函数基本是一致的。

#include<iostream>
#include<string>

using namespace std;

class Functor
{
 public:
        void operator()(const string& str) const
        {

            cout<< str << endl;
        }
    
}

int main(){
    Functor myFunctor;
    myFunctor("hello");
    return 0;
}

 六: lambda表达式举例

6.1:lambda表达式被:函数指针,auto,  function等方式接收

#include<iostream>
#include<string>
#include<functional>
#include "lambda_.h"
using namespace std;

typedef void (*p_nameFunc)(string name);

void use_lambda1() {
	// 1:匿名调用
	[](string name) {
	
		cout << "this is anonymous" << endl;
		cout << "hello" << endl;
	}("jack ma");

	// 2:通过auto赋值
	auto fname = [](string name)->string {
		cout << "this is auto" << endl;
		cout << "hello" << endl;
		return "hello world";
	};
	fname("Robin ma");

	// 函数指针
	p_nameFunc fname2 = [](string name)
	{
		cout << "this is P_nameFunc" << endl;
		cout << "hello " << name << endl;
	};
	fname2("liu");

	// 4:function
	function<void(string)> funcName;
	funcName = [](string name)
	{
		cout << "this is function" << endl;
		cout << "hello " << name << endl;
	};
	funcName("wang");
}

int main() {

	use_lambda1();
}

 6.2:lambda捕获方式

void use_lambda2() {
	int age = 33;
	int score = 100;
	string name = "jack";
	string job = "softengineer";

	// 值捕获
	[age, name](string name_)
	{
		cout << "age is: " << age << "  name is: " << name << " self-name is: " << name_ << endl;
		//  name = "xiaoli"; // error : 表达式必须是可修饰的左值
		//  age = 20;  //  error : 表达式必须是可修饰的左值
	}("vivo");

	// 引用捕获
	[&age, &name](string name_)
	{
		cout << "age is: " << age << " name is : " << name << "self-name is: " << name_ << endl;
		name = "xiaoli";
		age = 20;
	}("huawei");

	// 全部用值捕获,name用应用捕获
	[=, &name]()
	{
		cout << "age is: " << age << " name is: " << name << " score is: " << score << " job is: " << job << endl;
		name = "cui hua";
	}();

	//  全部用引用捕获,只有name 用值捕获
	[&, name]()
	{
		cout << "age is: " << age << " name is: " << name << " score is: " << score << " job is: " << job << endl;
	}();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值