• C++11 - 3 - lambda表达式


    c++

    前言:

    Vue框架:从项目学Vue
    OJ算法系列:神机百炼 - 算法详解
    Linux操作系统:风后奇门 - linux

    可调用对象:

    • 含义:具有传入参数,进行处理,传出结果的功能的对象
    • 分类:
      1. 函数:
      2. 函数指针:
      3. 仿函数对象:
      4. lambda表达式:
    • 举例:
    //1, 函数:
    void fmin(int x, int y){
    	return x<y?x:y;
    }
    //2,函数指针:
    void func(int, int) = fmin();
    func(1, 2);
    //3,仿函数对象:
    struct IntLess{
    	bool operator()(int &x, int &y){
    		return x<y?x:y; 
    	}
    }
    IntLess(1, 2);
    //4,简易lambda表达式:
    auto function = [](int x, int y){
    	return x<y?x:y;
    };
    function(1, 2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    lambda表达式:

    格式:

    • 可由二/三/四/五部分构成:
    //附加说明的五部分:附加关键词一般为mutable、noexcept
    auto func = [](int x, int y)mutable->int{
    	return x<y?x:y;
    }
    //完整的四部分:
    auto func1 = [](int x, int y)->int{
    	return x<y?x:y;
    };
    //省略返回类型,可自动推导返回类型
    auto func2 = [](int x, int y){
    	return x<y?x:y;
    };
    //当不需要参数时候,可省略参数
    auto func3 = []{
    	cout<< "hello world"<< endl;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 完整的四部分:
      1. [捕捉列表]
      2. (形参列表)
      3. ->返回值类型
      4. {函数体}
    • 附加的一部分:附加关键词
    • lambda表达式必须的两部分:[]{}
      可省略的两部分:()->

    捕捉列表:

    • 含义:向lambda表达式传递参数时,()中只能传值,想要传引用或地址时,需要利用捕捉列表
    • 作用:捕捉与lambda表达式处于同一作用域下的局部变量
    • 捕捉形式:
      1. 传值捕捉
      2. 传引用捕捉
    • 捕捉范围要求:
      1. 与lambda表达式处于同一作用域
      2. 只能捕捉局部变量
      3. 对于同一变量,不可以同时捕捉值和捕捉引用
    • 捕捉形式:
      1. 引用捕捉:
        1. 捕捉当前作用域下某变量的引用:
          &a->{}
        2. 捕捉当前作用域下所有变量的引用:
          &->{}
      2. 传值捕捉:
        1. 捕捉当前作用域下某变量值:
          a->{}
        2. 捕捉当前作用域下所有变量值:
          =->{}

    附加关键词:

    • mutable关键词:
      1. 作用:传值捕捉获得的变量默认是const的,想要对其进行写,需要加附件关键词mutable
      2. 放置位置:(形参)后直接附加,也就是说,使用mutable关键词时必须加(形参列表)
    • 举例:
    //报错:常量不可修改
    int main(){
    	int x = 0;
    	auto func = [=](){
    		x++;
    		cout<<x<<endl;
    	};
    	cout<<x<<endl;
    }
    
    //()mutable
    int main(){
    	int x = 0;
    	auto func = [=]()mutable{
    		x++;
    		cout<<x<<endl;
    	};
    	cout<<x<<endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    decltype表达式的本质:

    • lambda表达式本质就是仿函数类
    • 如同范围for的本质是迭代器
    • C++11中也为我们提供了推断变量类型的运算符号:decltype
    auto func = [](int x, int y){
    	return x<y?x:y;
    };
    cout<< decltype(func).name();
    
    • 1
    • 2
    • 3
    • 4
    • decltype和auto的区别:
      1. decltype用于需要声明变量类型的情况,如函数形参
      2. auto用于需要不声明变量类型的情况,如单纯使用

    • decltype使用:

    auto func1 = []{cout<<"极简lambda"<<endl;};
    auto func2 = func1;
    decltype(func1) func3 = func1;
    
    • 1
    • 2
    • 3

    捕捉列表和参数列表对比:

    实质:
    • lambda表达式转化为了仿函数类:
      1. 捕捉列表转化为了类内成员变量
      2. 参数转化为了类内函数参数
    作用域:
    • 形参列表() + mutable,传参来源可以是任何变量,当然不加mutable范围不变,写权限消失
    • 捕捉列表捕捉的对象只能是同作用域下的局部变量
    • 当对同作用域下的局部变量操作时,()+mutable和[]效果相同

    调用对象对比:

    lambda:

    • lambda表达式相对函数/函数指针/仿函数对象来说写作更快捷,

      适用于编写依据类的不同字段,对类的对象排序,类似这样的代码

    • 下面给出一个商品类,求分别按照商品价格/评分/名称,对商品对象进行排序:

    • 商品类:

    class Goods{
    	private:
    		int price;
    		double evaluate;
    		char* name;
    	public:
    		//八大默认函数,自动补全。
    		Goods(int _price, double _evaluete, char* _name){
    			price = _price;
    			evaluete = _evaluete;
    			name = _name;
    		}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 商品排序 - 基于lambda表达式:
    vector<Goods> v{{1, 1.0, "a"}, {2, 2.0, "b"}, {3, 3.0, "c"}, {4, 4.0, "d"}};
    sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    		return a.price > b.price;
    	});
    sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    		return a.price < b.price;
    	});
    sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    		return a.evaluete > b.evaluete;
    	});
    sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    		return a.evaluete < b.evaluete;
    	});
    sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    		return strcmp(a.name, b.name);
    	});
    sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    		return -1*strcmp(a.name, b.name);
    	});
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    函数指针:

    • 商品排序 - 基于函数/函数指针:
    bool ComparePriceLess(Goods &a, Goods &b){
    	return a.price < b.price;
    }
    bool ComparePriceMore(Goods &a, Goods &b){
    	return a.price < b.price;
    }
    bool CompareEvaluateLess(Goods &a, Goods &b){
    	return a.price < b.price;
    }
    bool CompareEvaluateMore(Goods &a, Goods &b){
    	return a.price < b.price;
    }
    bool CompareNameLess(Goods &a, Goods &b){
    	return a.price < b.price;
    }
    bool CompareNameMore(Goods &a, Goods &b){
    	return a.price < b.price;
    }
    vector<Goods> v{{1, 1.0, "a"}, {2, 2.0, "b"}, {3, 3.0, "c"}, {4, 4.0, "d"}};
    sort(v.begin(), v.end(), ComparePriceLess);
    sort(v.begin(), v.end(), ComparePriceMore);
    sort(v.begin(), v.end(), CompareEvaluateLess);
    sort(v.begin(), v.end(), CompareEvaluateMore);
    sort(v.begin(), v.end(), CompareNameLess);
    sort(v.begin(), v.end(), CompareNameMore);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    仿函数对象:

    • 商品排序 - 基于仿函数:
    struct ComparePriceLess{
    	bool operator()(Goods &a, Goods &b){
    		return a.price < b.price;
    	}
    };
    struct ComparePriceMore){
    	bool operator()(Goods &a, Goods &b){
    		return a.price > b.price;
    	}
    };
    struct CompareEvaluateLess{
    	bool operator()(Goods &a, Goods &b){
    		return a.evaluate < b.evaluate;
    	}
    };
    struct CompareEvaluateLess{
    	bool operator()(Goods &a, Goods &b){
    		return a.evaluate > b.evaluate;
    	}
    };
    struct CompareNameLess{
    	bool operator()(Goods &a, Goods &b){
    		return -1*strcmp(a.name, b.name);
    	}
    };
    struct CompareNameLess{
    	bool operator()(Goods &a, Goods &b){
    		return strcmp(a.name, b.name);
    	}
    };
    vector<Goods> v{{1, 1.0, "a"}, {2, 2.0, "b"}, {3, 3.0, "c"}, {4, 4.0, "d"}};
    sort(v.begin(), v.end(), ComparePriceLess());
    sort(v.begin(), v.end(), ComparePriceMore());
    sort(v.begin(), v.end(), CompareEvaluateLess());
    sort(v.begin(), v.end(), CompareEvaluateMore());
    sort(v.begin(), v.end(), CompareNameLess());
    sort(v.begin(), v.end(), CompareNameMore());
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
  • 相关阅读:
    DBPack SQL Tracing 功能及数据加密功能详解
    windows编程之计时器
    【C++】set和map的底层结构(AVL树&红黑树)
    ssl证书自动化快速部署和续费经验分享
    昨天面试一个武大的,10年经验,薪资只要1万二!
    Mac M1安装Centos8
    如何隐藏woocommerce 后台header,woocommerce-layout__header
    栈和队列及表达式求值问题
    .Net依赖注入神器Scrutor(上)
    Nginx基础理论
  • 原文地址:https://blog.csdn.net/buptsd/article/details/126883125