前言
返回值后置
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; // errorcout << "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; // errorcout << "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; // okconst int& cra = a; // okconst int b = 10;
// int& rb = b; // errorconst 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; // oke = 666; // ok 通過右值引用不會喪失修改目標內存的權限
// int&& f = a; // error// 常左值引用(萬能引用),既能引用左值,也能引用右值const int& g = a; // okconst int& h = a + c; // ok
// g = 666; // error 但是通過常左值引用會喪失修改目標內存的權限return 0;
}
移動語義
資源的轉移 代替 資源的重建
保證功能正確的情況下,做到性能提升