1.lambda(可以说是该匿名函数的统称)
1.捕捉分两种:值捕捉和引用捕捉
int main()
{
int a =10,b = 20;
//a是值拷贝,b是引用拷贝
auto add = [a,&b](int x,int y)->int{return x + y + a + b;}
return 0;
}
值捕捉在函数体内是不允许被修改的,引用捕捉允许被修改且会影响外部的该变量的值。
全局域与局部静态变量可以直接使用且不允许被捕捉,同一个变量也不允许被捕捉两次及以上。
lambda也是可以直接载全局中实现的,只是一般写在函数内。
3.隐式值捕捉:[=]=>默认将该函数内的局部变量的值都捕捉进来
隐式引用捕捉:[&]=>默认将该函数内的局部变量的引用都捕捉进来
上面两种即使全捕捉,但函数体未使用的变量实际上并没有被捕捉。
混合捕捉:
//除了a,b是值捕捉,其他都引用捕捉
[&,a,b]
4.lambda是不能递归:
lambda是匿名函数给函数变量初始化完了之后才能使用(常规函数没有运行初始化这种概念才可以递归)因此lambda的内部无法调用未初始化完的函数变量。
//类似于我初始化我自己,逻辑矛盾
int a = a + 10;
5.mutable
允许值捕捉的变量的值也能被修改,但这里修改的值并不会影响外部局部变量的值
auto add[a,&b](int x,int y) mutable
{
a++;
return x + y;
}
6.lambda的原理(就是仿函数)
cpp
class Rate
{
public:
Rate(double rate)
: _rate(rate)
{
}
double operator()(double money, int year)
{
return money * _rate * year;
}
private:
double _rate;
};
int main()
{
double rate = 0.49;
// lambda
auto r2 = [rate](double money, int year) {
return money * rate * year;
};
// 函数对象
Rate r1(rate);
r1(10000, 2);
r2(10000, 2);
return 0;
}
反汇编
cpp
//二者的形成逻辑很像
auto r2 = [rate](double money, int year) {
return money * rate * year;
};
00007FF6D1DB20EB lea rdx,[rate]
00007FF6D1DB20EF lea rcx,[r2]
00007FF6D1DB20F3 call `main'::`2'::<lambda_1>::<lambda_1> (07FF6D1DB18D0h)
00007FF6D1DB20F8 nop
// 函数对象
Rate r1(rate);
00007FF6D1DB20F9 movsd xmm1,mmword ptr [rate]
00007FF6D1DB20FE lea rcx,[r1]
00007FF6D1DB2102 call Rate::Rate (07FF6D1DB1474h)
00007FF6D1DB2107 nop
cpp
//二者插入值得方式完全一样
r1(10000, 2);
00007FF6D1DB2108 mov r8d,2
00007FF6D1DB210E movsd xmm1,mmword ptr [__real@40c3880000000000 (07FF6D1DBABB0h)]
00007FF6D1DB2116 lea rcx,[r1]
00007FF6D1DB211A call Rate::operator() (07FF6D1DB1479h)
00007FF6D1DB211F nop
r2(10000, 2);
00007FF6D1DB2120 mov r8d,2
00007FF6D1DB2126 movsd xmm1,mmword ptr [__real@40c3880000000000 (07FF6D1DBABB0h)]
00007FF6D1DB212E lea rcx,[r2]
00007FF6D1DB2132 call `main'::`2'::<lambda_1>::operator() (07FF6D1DB1DC0h)
00007FF6D1DB2137 nop
2.默认移动构造和默认移动赋值
在没有自主实现得移动构造,析构函数,拷贝构造,拷贝赋值中的任意一个时编译器才会生成一个默认移动构造/移动赋值。
两个得功能也完全一样:内置类型成员值拷贝,自定义类型成员变量优先调用移动构造,没有在调用拷贝构造。
3.deflaut
其实所有得默认成员函数都可以通过deflaut来强制生成.
cpp
//强制生成默认构造
List_node() = deflaut;
//强制生成拷贝构造
List_node(cosnt List_node& a) = deflaut;
delete:不允许外部调用该成员函数,例ostream的拷贝函数就不允许调用

STLC++11的最核心变化就是unorded_map的unoreded_set容器的出现,与容器中push系列/insert/emplace系列这里面与右值引用相关的接口。
4.包装器
1.function(函数模板同时还是一个参数包),原理无需懂,在functional头文件中。
cpp
template<class T>
class function
template<class Ret,class... Args>
class function<Ret<Args...>>
使用:(function的参数个数,类型,返回值都要与右侧的可调用对象的相同)
cpp
#include<functional>
int f(int a, int b)
{
return a + b;
}
struct Functor
{
public:
int operator() (int a, int b)
{
return a + b;
}
};
int main()
{
// 包装各种可调用对象,常规函数,仿函数,匿名函数
function<int(int, int)> f1 = f;
function<int(int, int)> f2 = Functor();
function<int(int, int)> f3 = [](int a, int b) {return a + b; };
return 0;
}
说白了就是代替c语言的函数指针的。
cpp
class Plus
{
public:
Plus(int n = 10)
:_n(n)
{}
static int plusi(int a, int b)
{
return a + b;
}
double plusd(double a, double b)
{
return (a + b) * _n;
}
private:
int _n;
};int main()
{
//都要取地址
function<int(int, int)> f4 = &Plus::plusi;
cout << f4(1, 1) << endl;
//常规成员函数还有this指针的隐藏函数,这里要写一个Plus类型的函数
function<double(Plus*, double, double)> f5 = &Plus::plusd;
Plus pl;
cout << f5(&pl, 1.111, 1.1) << endl;
function<double(Plus, double, double)> f5 = &Plus::plusd;
Plus pl;
cout << f5(pl, 1.111, 1.1) << endl;
return 0;
}
&是必然的,static成员函数没有this指针,因此不用传Plus,但常规成员函数有this指针,因此要传。
此处的Plus变量其实不能说完全就是this指针,其的本质是.*,有
cpp
pl.*(成员函数地址);
bind(返回一个functional类型)
起的本质是一个函数模板,也就是一个可调用对象的包装器,用于调整参数个数与参数顺序。
placeholders,是占位符的集合
cpp
//常要using来简化placeholders
using placeholders::_1;
using placeholders::_2;
using placeholders::_3;
int Sub(int a, int b)
{
return (a - b) * 10;
}
int SubX(int a, int b, int c)
{
return (a - b - c) * 10;
}
int main()
{
//第一次bind可以视为初始化placeholders
auto sub1 = bind(Sub, _1, _2);
cout << sub1(10, 5) << endl;
//就可以反过来传参了
auto sub2 = bind(Sub, _2, _1);
cout << sub2(10, 5) << endl;
// 调整参数个数
//锁死了两个参数,只有_1能传了
auto sub3 = bind(Sub, 100, _1);
cout << sub3(5) << endl;
auto sub4 = bind(Sub, _1, 100);
cout << sub4(5) << endl;
// 分别绑死第123个参数
auto sub5 = bind(SubX, 100, _1, _2);
cout << sub5(5, 1) << endl;
auto sub6 = bind(SubX, _1, 100, _2);
cout << sub6(5, 1) << endl;
auto sub7 = bind(SubX, _1, _2, 100);
cout << sub7(5, 1) << endl;
function<double(Plus&&, double, double)> f6 = &Plus::plusd;
Plus pd;
cout << f6(move(pd), 1.1, 1.1) << endl;
cout << f6(Plus(), 1.1, 1.1) << endl;
// 成员函数对象进行绑死,就不需要每次都传递了
// 还能帮助function传plusd的地址
function<double(double, double)> f6 = bind(&Plus::plusd, Plus(), _1, _2);
cout << f6(1.1, 1.1) << endl;
return 0;
}
-1,-2的意思是代表要传的第几个实参,而非这个实参在所有参数中的排列顺序。