前言
返回值后置
auto 函数名 (形参表) ->decltype(表达式)
lambda表达式
lambda表达式的名称是一个表达式 (外观类似函数),但本质绝非如此
语法规则
[捕获表] (参数表) 选项 -> 返回类型
{
函数体;
}
lambda表达式的本质
- lambda表达式本质其实是一个类
- 并且最终返回值为这个类的对象
- 因此对lambda表达式的调用就是该对象的函数操作符的调用
简写
- 可以没有返回值类型,将根据return推断
- 如果连return也没有,则返回值为void
- 参数为void可以省略不写
捕获表
[]
:不捕获任何外部变量[variable]
: 捕获外部变量的值(具备只读属性)[&variable]
: 按引用捕获,指定的外部变量[this]
: 捕获this指针,访问外部对象的成员[=]
: 按值捕获所有的外部变量,也包括this[&]
: 按引用捕获所有的外部变量,也包括this[=,&variable]
: 按值捕获所有的外部变量包括this,但是指定的外部变量按引用捕获[&,=variable]
: 按引用捕获所有的外部变量,也包括 this,但是指定的外部变量按值捕获
// lambda表达式
#include <iostream>
#include <typeinfo>
using namespace std;
int Max(int x, int y){
return x > y ? x : y;
}
int main( void ){
int a = 10, b = 20;
cout << Max(a,b) << endl;;
auto f = [](int x, int y)->int{ return x > y ? x : y; };
// 编译器根据lambda表达式(1)生成一个类 (2)类内定义函数操作符函数 (3)返回这个类的匿名对象
/*
class Z4mainEUliiE_{
public:
int operator()(int x, int y){
return x > y ? x : y;
}
};
auto f = Z4mainEUliiE_{};
*/
cout << "f的类型:" << typeid(f).name() << endl;
cout << f(a,b) << endl; // f.operator()(a,b)
// lambda表达式可以没有返回值类型,根据return判断
cout << [](int x, int y) { return x+y; }(a,b) << endl;
/*
class X{
public:
auto operator()(int x, int y)->decltype(x+y){
return x + y;
}
};
cout << X{}(a,b) << endl; // cout << X{}.operator()(a,b) << endl;
*/
// lambda表达式可以没有返回类型,也没有retrun语句,返回类型为void
[](int x, int y){ cout << x << ' ' << y << endl; }(a,b);
/*
class XX{
public:
void operator()(int x, int y){
cout << x << ' ' << y << endl;
}
};
XX{}(a,b); // XX{}.operator()(a,b)
*/
// 如果没有形参,可以省略不写
[]{ cout << "无聊" << endl;}();
/*
class XXXX{
public:
void operator(){
cout << "无聊" << endl;
}
};
XXXX{}(); // XXXX().operator()()
*/
return 0;
}
// lambda表达式 -- 捕获表(捕获lambda表达式外部的变量信息)
#include <iostream>
#include <typeinfo>
using namespace std;
int a = 10;
class Y{
public:
void foo(/* Y* this */ int c = 30 ){
cout << "-------------[]----------------" << endl;
[](int d = 40){
cout << "a=" << a << endl;
cout << "b=" << b << endl;
// cout << "c=" << c << endl; // error
cout << "d=" << d << endl;
// cout << "e=" << e << endl; // error
}();
/*
class X{
public:
void operator()(int d = 40)){
cout << "a=" << a << endl;
cout << "b=" << b << endl;
// cout << "c=" << c << endl; // error
cout << "d=" << d << endl;
// cout << "e=" << this->e << endl; // error
}
};
X{}();
*/
cout << "-------------[c]----------------" << endl;
// 捕获外部变量的值
[c](int d = 40){ cout << "c=" << /*++*/c << endl; }();
/*
class XX{
public:
XX(int m):c(m){} //这里的c并不是foo函数的形参,而是XX类的一个成员变量
void operator()(int d = 40){
cout << "c=" << c << endl; // //这里的c并不是foo函数的形参,而是XX类的一个成员变量
}
private:
const int c; //这里的c并不是foo函数的形参,而是XX类的一个成员变量
};
XX{c}(); // 这里的c是foo函数的形参c XX(c).operator()()
*/
cout << "-------------[&c]----------------" << endl;
[&c](int d = 40){ cout << "c=" << ++c << endl; }();
cout << "-------------[&c]----------------" << endl;
[this](int d = 40){ cout << "e=" << e << endl; }();
}
private:
static int b;
int e;
};
int Y::b = 20;
int main( void ){
Y y;
y.foo();
return 0;
}
右值引用
左值 和 右值
- 可以“取”地址的值就是左值,左值通常具名
- 不可“取”地址的值就是右值,右值通常匿名
左值引用 和 右值引用
- 左值引用只能引用左值,不能引用右值
int a;
int& b = a; // OK
int c;
int& d = a + c; // ERROR
- 右值引用只能引用右值,不能引用左值
int&& e = a + c;// OK
int&& f = a; // ERROR
- 常左值引用,既能引用左值,也能引用右值
const int& g = a + c; // OK
const int& h = a; // OK
没有必要有常右值引用,因为常右值引用,完全可以被常左值引用替代
// 左值/右值 左值引用/右值引用
#include <iostream>
using namespace std;
int foo( ) {
int m=888;
return m;
}
int main( void ) {
// 当前作用域的生命期
// 具名内存-->能够取址-->左值|非常左值(无const修饰)
// |常左值 (有const修饰)
int a = 10;
int& ra = a; // ok
const int& cra = a; // ok
const int b = 10;
// int& rb = b; // error
const int& crb = b; // ok
// 语句级生命期(引用可以延长右值的生命期)
// 匿名内存-->不能取址-->右值|直接更改右值毫无意义(98/03标准给出结论)
// | 11标准认为给了真名就可以改
const int& ri = 10;
int&& rri = 10;
const int& rf = /*|888|*/foo( ); // (1)分配一块内存空间 (2)生成跳转指令
int&& rrf = foo();
return 0;
}
//左值引用/右值引用
#include <iostream>
using namespace std;
int main( void ) {
int a,c;
// 左值引用只能引用左值,不能引用右值
int& b = a; // ok
// int& d = a + c; // error
// 右值引用只能引用右值,不能引用左值
int&& e = a + c; // ok
e = 666; // ok 通过右值引用不会丧失修改目标内存的权限
// int&& f = a; // error
// 常左值引用(万能引用),既能引用左值,也能引用右值
const int& g = a; // ok
const int& h = a + c; // ok
// g = 666; // error 但是通过常左值引用会丧失修改目标内存的权限
return 0;
}
移动语义
资源的转移 代替 资源的重建
保证功能正确的情况下,做到性能提升