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 这个办法可以将左值参数转化为右值
-