C++可调用对象
对于一个对象或表达式,若果可以对其使用调用运算符,则称他为可调用的。
函数调用对象:函数、函数指针、重载了调用运算符的类和lambda表达式。
一、函数
格式:
return_type func_name(parameters…){function_body}
auto func_name(parameters…)->return_type{function_body}
int add(const int &a, const int &b)
{
return a + b;
}
auto sub(const int &a, const int &b)->int
{
return a - b;
}
int main(int argc, char** argv)
{
std::cout << add(1,2) << std::endl;
std::cout << sub(1,2) << std::endl;
return 0;
}
二、函数指针
格式:
函数定义格式:return_type func_name(parameters…){function_body};
函数指针格式(在函数明前加’*’):return_type (*func_name)(parameters…){function_body};
#include<iostream>
int add(const int &a, const int &b)
{
return a + b;
}
typedef int (*fun)(const int &a, const int &b);
int main(int argc, char **argv)
{
fun l_add = add;
std::cout << l_add(1,2) << std::endl;
int (*l_add2)(const int &a, const int &b) = add;
std::cout << l_add2(3,4) << std::endl;
return 0;
}
三、重载了调用运算符的类
如果类定义了调用运算符,则该类的的对象成为函数对象。
格式:
return_type operator()(parameters…){function_body}
class absInt{
public:
absInt(){};
~absInt(){};
public:
int operator()(const int &a, const int &b)
{
return a + b;
}
};
int main(int argc, char **argv)
{
absInt myint;
std::cout << myint(1,2) << std::endl;
return 0;
}
四、lambda表达式
1)概念
lambda表达式:一个可调用的代码单元,可理解为一个未命名的内联函数。
lambda与函数类似,有返回值类型、参数列表和函数体;
不同的是:
lambda可定义在函数内部;
lambda有一个捕获列表用来捕获所在函数体内的局部变量(通常为空);
lambda必须使用尾置返回来指定返回值类型;
lambda不能有默认参数,实参数目必须与形参数目相同;
2)组成
[capture list] (parameter list)->return type{function body}
我们可以忽略lambda的参数列表和返回类型,但是必须永远包含捕获列表和函数体,lambda根据函数体内的代码推断返回类型。
3)使用
1、传递参数:
auto add = [](const int &a, const int &b){return a + b};
std::cout << add(1,2) << std::endl;
2、使用捕获列表:
int comp = 30;
auto fun = \
[comp]()\
{\
if(comp > 20)\
{\
std::cout << "Target bigger" << std::endl;\
}\
};
fun();
lambda的捕获和返回:
当定义一个lambda时,编译器生成一个与lambda对应的新的(未命名)的类类型。此处可理解为:当向函数传递一个lambda实例时,同时定义了一个新类型和该类型的一个对象:传递的参数是编译器生成的类类型的未命名对象。默认情况下,从lambda生成的类都包含一个对应该lambda所捕获的变量的数据成员,在对象创建时被初始化。
#include<iostream>
int main(int argc, char **argv)
{
//值传递:被捕获的变量必须可拷贝,在创建时进行拷贝,而不是调用时。
{
int a = 10;
auto copy = [a](){return a;};
a = 0;
auto b = copy();
std::cout << " b = " << b << std::endl;
}
//引用捕获:必须确保被引用的对象在lambda执行时是存在的。
{
int a = 10;
auto copy = [&a](){return a;};
a = 0;
auto b = copy();
std::cout << " b = " << b << std::endl;
}
//隐式捕获:在[]写入'='或'&'告知编译器捕获方式为值捕获或引用捕获,编译器根据表达式中代码推断捕获列表
{
int a = 0;
auto fun = [=](const int& tmp){return a > tmp;};
std::cout << a << " > " << 100 << " ? " << fun(100) << std::endl;
}
return 0;
}
返回:必须使用尾置返回类型。
{
int a = -10;
auto absolute = [](int tmp)->int {if(0 > tmp)return -tmp;return tmp;};
a = absolute(a);
std::cout << " a = " << a << std::endl;
}