model C++ :Lambda表达式、function、bind、placeholder、右值引用

Lambda表达式

基本语法

[捕获列表](参数列表) mutable(可选) 异常属性 -> 返回类型 {
// 函数体
}
//简化版本 
//只要有mutable(可选) 异常属性 -> 返回类型就需要()
[捕获列表]{
// 函数体
}
  • 作用
    • 需要一个参数,又不想费力去命名一个函数。即想要创建一个匿名函数
  • 各个部分的作用
    • 捕获列表
      • 捕获列表可以起到传递外部数据的作用,不是传入,是允许多去的外部数据
    • 参数列表
      • 外部传入的参数和函数相同
    • mutable
      • 表示捕获的参数是否可变,无mutable参数只读
    • ->返回值类型
      • 由于是从[]开始所以返回类型滞后。

捕获列表分类

  • 值捕获

    • 只是值拷贝,一般为只读,加mutable允许变化但是只是拷贝值的变化
  • 引用捕获

    • auto copy_value = [&value] {
      return value;
      };
      
    • 与引用传参类似,引用捕获保存的是引用,值会发生变化。

  • 隐式捕获

    • 用&或者= 代替,向编译器声明,让编译器自动寻找
  • 表达式捕获

    • 捕获都是外层作用域声明的变量,因此捕获方法均为左值,而不能捕获右值
    • C++14允许右值捕获,捕获变量类型会根据表达式进行判断

泛型Lambda

  • C++20 之前auto关键字不能用在参数表里

    auto func(auto a, auto b)
    {
    	return a+b;
    }
    
  • C++14支持参数列表里面可以用auto来进行修饰

    auto add =[](auto a, auto b){
    	return a+b;
    }
    

函数对象包装器

std :: function

  • Lambda表达式本质是和函数对象类型相似的类类型

  • 当捕获列表为空时,闭包对象还可以作为函数指针进行传递

    #include <iostream>
    using foo = void(int); // 定义函数类型, using 的使用见上一节中的别名语法
    void functional(foo f) { // 参数列表中定义的函数类型 foo 被视为退化后的函数指针类型 foo*
        f(1); // 通过函数指针调用函数
    }
    int main() {
        auto f = [](int value) {
        std::cout << value << std::endl;
    	};
        functional(f); // 传递闭包对象,隐式转换为 foo* 类型的函数指针值
        f(1); // lambda 表达式调用
        return 0; 
    }
    
    
    //C++11 std::function 是一种通用、多态的函数封装,可以把它看成是一种函数容器
    //需要指定返回值类型和参数类型在< > 里面
    //比如返回一个 指向返回值为int 参数为int的类型
    //std::function<int(int)> fc = foo
    int foo (int para)
    {
    	return para;
    }
    int main()
    {
    	std :: function<int(int)> func = foo;
    	int important = 10;
    	std :: function<int>(int)> = [](int x)->int{
    		return x+10 ;
    	}
    	std::cout << func(10) << std::endl;
    	std::cout << func2(10) << std::endl;
    }
    
    

std::bind std::placeholder

  • bind函数就是将参数绑定在函数上,可以使用placeholder来作为占位符,并使用_1 来表示占位
int functionc(int a ,int b, int c){
	return a + b + c;
}
auto bFc = bind(functionc, _1,2,3); //绑定后形成一个新的函数
//位置时相较于剩余位置来占位的
auto bindFunc = bind(add,1,placeholders::_2,placeholders::_1);// a = 1 ,b = 2 , c = 10 ;
auto bindFunc = bind(add,placeholders::_2,placeholders::_1,1);// a = 2 ,b = 10 , c = 1 ; 
cout<< bindFunc(10,2)<<endl;
bFc(1); 

右值引用

左值、右值的纯右值、将亡值、右值

  • 左值:赋值在等号左边的值,是个表达式后依然存在的持久对象。

  • 右值:右边的值,是指表达式结束后就不再存在的临时对象

    • 纯右值

      • 字面量:10、true

      • 求值结果是字面值或匿名对象:1+2 ,

      • 非引用返回的临时变量、运算表达式产生的临时变量、原始

        字面量、Lambda 表达式都属于纯右值。

      • 字符串字面量为const char [];

        //C++ char*,const char*,string的相互转换
        1、string转const char *
        
        string s = "abc";
        const char * c_s = s.c_str();
        
        2、const char* 转string
        const char * c_s = "abc";
        string s(c_s); 
        
        3、char * 转string 
        char c  = "abc"
        string s(c);
        4、string 转char * 
        
        string s = "abc"
        int len = s.length();
        char *c = new char[len+1];
        strcpy(c,s.c_str());
        
        5、const char * 转char * 
        const char * c_s = "abc";
        char * c = new char[100];//足够长3
        strcpy(c,c_s);
        
      • "01234"的类型是const char [6]

        • const char * 是右值,“01234”可以隐式转换为const char *
    • 将亡值

      std::vector<int> foo() {
          std::vector<int> temp = {1, 2, 3, 4};
          return temp;
      }
      
      • 函数内部创建,在离开函数作用域会被回收,如果进行返回需要先拷贝一份,然后在进行销毁,如果temp非常大,消耗会非常大

      • 解决方法:

        可以将左值进行隐式右值转换
        
        auto a  = static_cast<vector<int>&&>(temp) //
        return a ;//此时如果返回temp就是为空
        
    • 拿到右值的方法

      右值引用:T &&
      std::move 这个办法可以将左值参数转化为右值
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值