std::function与可调用对象
可调用对象是指那些像函数一样可以直接被调用的对象,他们广泛用于C++的算法,回调,事件处理等机制。
函数指针
函数指针是最简单的一种可调用对象
我们大家应该都用过函数名来作为函数的地址,但是函数名称其实与函数的地址是有一些细微的差别的
void printHello() {
std::cout << "Hello, World!" << std::endl;
}
以上面的函数为例,函数的名称是printHello, 但是它的类型其实是void() , 而不是void(*)(),但是它可以被隐式的转化成void( * ),
void (*ptr)() = printHello;
在上面这行代码中,printHello会被隐式转化为void( * )(), 这就跟char [] 能被隐式的转化为char *很类似
如下代码也能完成上述转化,但是是显示的取函数地址
void (*ptr)() = &printHello
显示利用&运算符取地址
言归正传,在得到函数指针之后,我们就可以直接通过函数指针调用函数,并且可以将其作为一些函数的参数
例如:
bool cmp( int a, int b)
{
return a < b;
}
std::vector<int> vec = {2,1,4,3,7,6};
std::sort(vec.begin(),vec.end(),cmp);
上述例子就会将容器vec中的元素从小到大进行一个排序了。
lambda表达式
lambda是C++11引入的一种匿名函数对象,提供了一种简单的方式用来定义内联函数,它的标准格式如下:
[capture-list] (parameters) -> return-type { body }
[capture-list] 捕获列表,捕获的变量可以在lambda表达式的函数体内使用
(parameters) 参数列表,与函数的参数列表一致
-> return-type 返回值,如果不写,lambda表达式会自动推导返回值
{body} 函数体
既然返回值可以省略,lambda表达式最常见的格式就是
[](){
}
其中
[&x] 表示用引用的方式捕获变量x
[x] 表示用值捕获的方式捕获变量x
[=] 按值捕获的方式捕获作用域内所有变量
[&] 按引用捕获的方式捕获作用域内所有变量
[a, &b] 按值捕获a, 按引用捕获b
lambda表达式最简单的使用方式:
auto lambda = [](){
std::cout << "Hello World" << std::endl;
};
lambda();
int x = 5;
auto lambda = [x](int a){
return x + a;
};
lambda(6);
如上图两个例子所示,lambda表达式可以就像普通函数那样被调用
lambda表达式的类型
auto lambda = [](){
std::cout << "Hello World" << std::endl;
};
你知道此时auto是什么类型吗?
编译器会为每一个lambda表达式,生成如下面所示的一个类:
class __lambda_1 {
public:
void operator()() const {
std::cout <&l