网站首页 全球最实用的IT互联网站!

人工智能P2P分享Wind搜索发布信息网站地图标签大全

当前位置:诺佳网 > 软件工程 > 后端开发 > C++ >

Lambda表达式

时间:2026-03-17 16:24

人气:

作者:admin

标签:

导读:用法 C11加入了Lambda表达式,这是现代编程语言的一个特点,lambda表达式的优点: 声明式的编程风格:就地匿名定义目标函数或者函数对象,不需要额外写一个声明函数或者函数对象。类...

用法

C++11加入了Lambda表达式,这是现代编程语言的一个特点,lambda表达式的优点:

  • 声明式的编程风格:就地匿名定义目标函数或者函数对象,不需要额外写一个声明函数或者函数对象。类似匿名内部类。
  • 简洁:避免了代码膨胀和功能分散,让开发更加高效。
  • 在需要的时间和地点实现功能闭包,是程序更加灵活。

lambda表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。

语法形式:

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

其中capture是捕获列表,params是参数列表,opt是函数选项,ret是返回值类型,body是函数体;下面逐个详细介绍。

  • 捕获列表capture:捕获一定范围内的变量,具体使用方式

    []:不捕获任何变量。

    [&]:捕获外部作用域中所有变量,并作为引用在函数体内使用(按引用捕获)

    [=]:捕获外部作用域中所有变量,并作为副本在函数体内使用(按值捕获),拷贝的副本在匿名函数体内部是只读的。如果想要修改需要添加函数选项mutable。

    #include <iostream>
    using namespace std;
    
    void func(int x, int y) {
    	int a = 7;
    	int b = 9;
    	[=, &x](int z) mutable {
    		int c = a;
    		int d = x;
    		b++;
    		cout << "bb: " << b << endl;
    		}(88);    //没有(88)就只是匿名函数的定义,并没有调用。(88)是调用。因为有参数,所有传入的参数是88,如果没有参数就是();
    	cout << "b: " << b << endl;
    }
    
    int main() {
    	func(1, 2);
    	system("pause");
    	return 0;
    }
    

    如果没有mutable变量b++就会报错。且这里是按值捕获所以这里在lambda里面的修改不会影响到外部变量。

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

    [bar]:按值捕获bar变量,同时不捕获其他变量。

    [&bar]:按引用捕获bar变量,同时不捕获其他变量。

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

    #include <iostream>
    using namespace std;
    
    class Test {
    public:
    	void output(int x, int y) {
    		auto x1 = [] {return m_number; };                    //error
    		auto x2 = [=] {return m_number + x + y; };           //ok
    		auto x3 = [&] {return m_number + x + y; };           //ok
    		auto x4 = [this] {return m_number; };                //ok
    		auto x5 = [this] {return m_number + x + y; };        //error
    		auto x6 = [this, x, y] {return m_number + x + y; };  //ok
    		auto x7 = [this] {return m_number++; };              //ok
    	}
    	int m_number = 100;
    };
    

    x1:错误,没有捕获外部变量,不能使用类成员 m_number
    x2:正确,以值拷贝的方式捕获所有外部变量
    x3:正确,以引用的方式捕获所有外部变量
    x4:正确,捕获this指针,可访问对象内部成员
    x5:错误,捕获this指针,可访问类内部成员,没有捕获到变量x,y,因此不能访问。
    x6:正确,捕获this指针,x,y
    x7:正确,捕获this指针,并且可以修改对象内部变量的值

  • 参数列表params:和普通函数的参数列表一样,如果没有参数参数列表可以省略不写。

    auto f = [](){return 1;}  //没有参数,参数列表为空
    auto f = []{return 1;}    //没有参数,参数列表省略不写。
    
  • 函数选项opt:

    有两个类型 mutable 和 exception 两种,不需要可以省略。

    mutable:可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)。

    exception:指定函数抛出的异常,如抛出整数类型的异常,可以使用throw()

  • 返回值类型:在C++11中,lambda表达式的返回值是通过返回值后置语法来定义的。

    很多时候,lambda表达式的返回值是非常明显的,因此在c++11中允许省略lambda表达式的返回。

    //完整的lambda表达式定义
    auto f = [](int a) -> int{
        return a+10;
    };
    
    //忽略返回值的lambda表达式定义
    auto f = [](int a) {
        return a+10;
    };
    

    一般情况下,不指定lambda表达式的返回值,编译器会根据return语句自动推导返回值的类型,但需要注意的是初始化列表不能用于返回值的自动推导

    //可以自动推导出返回值类型
    auto f = [](int i){
        return i;
    }
    
    //不能推导出返回值类型
    auto f1 = [](){
        return {1, 2};  //基于列表初始化推导返回值,error。
    }
    

    因为通过初始化列表可以初始化的类型很多,比如初始化一个数组int[],初始化一个结构体等很多,所以不能确定初始化的类型,因此需要把初始化的类型写出来。

  • 函数体:函数的实现,这部分不能省略,但函数体可以为空。

lambda本质

lambda可以看作是一种 可调用对象 。

C++中的可调用对象有四种:(1)函数指针、(2)仿函数、(3)可以转换为函数指针的函数对象、(4)类里面的成员函数以及类里面的成员变量。

在c++中lambda可以被看做是一个仿函数。operator()的类。

按照c++标准,lambda表达式的operator()默认是const的,一个const成员函数是无法修改成员变量值的。

mutable选项的作用就是在于取消operator()的const属性。

因为lambda表达式在c++中会被看作是一个仿函数,因此可以使用std::function(可调用函数包装器)进行包装称为函数指针,或者用std::bind绑定称为仿函数;但是如果没有捕获列表可以直接当一个函数指针看待。

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

void func(int x, int y) {
	int a;
	int b;
	using ptr = void(*)(int);   //定义一个函数指针。
	ptr p1 = [](int x) {
		cout << "x:" << x << endl;
		};
	p1(11);

	function<void(int)> fff = [=](int x) {     //function<返回值类型(参数类型)>
		cout << "x:" << x << endl;
		};
	fff(11);

	function<void(int)> ffu = bind([=](int x) {     //也可以用auto进行推导类型,用auto推导的类型和function<void(int)>不是一个类型。因为auto推导的是仿函数类型,function<void(int)>是包装器对象类型。但是包装器类型可以包装auto推导出的类型
		cout << "x: " << x << endl;
		},placeholders::_1);          //placeholders::_1是一个占位符          
	ffu(11);

}

int main() {
	system("pause");
	return 0;
}
温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信