std::function和std::bind的头文件都为#include <functional>
1、function是一个模板,跟使用其他模板一样,只不过一般用来定义函数类型模板。function操作有以下形式:
(1)function<T> f; f是用来存储可调用对象的空function
(2)function<T>f(nullptr) 显示构造一个空fucntioin
(3)function<T>f(obj) 在f中存储可调用对象obj的副本
(4)f(args) 调用f中的对象,参数是args
上述T为函数类型,即返回类型和参数类型。
eg:std::function<int(int,int)>//定义一个返回类型为int,形参类型为int,int的函数对象。
2、bind的形式如下:
auto newCallable = bind(callable,arg_list)
newCallable为右边bind生成新的可调用对象。callable可调用的函数,arg_list为逗号分隔的callable的参数列表。当我们调用newCallable时,newCallable会调用callable,并传递给它arg_list中的参数(需要注意的是当arg_list的参数为std;:placeholders::_1,,,时,传递的参数为newCallable调用callable函数时传递的实参,而不是定义时绑定的参数)。
3、lambda表达式表示一个可调用的代码单元,当函数体较少时,可定义lambda表达式。形式如下:
[capture list](parameter list)->return type{function body}
(1)capture list为lambda表达式所在上下文环境中变量的捕获,可以捕获当个变量[var1],也可以捕获整个变量[this];捕获的值用于{}函数体语句中的变量访问(例如算式运算、访问)。捕获列表方式有三种:值捕获[var1]、引用捕获[&var1]、值与引用捕获混合使用eg: [&,identifier_list]。
当然也可不用捕获lambda表达式所在上下文变量,即[]。注意书写时,捕获列表符号“[]”不能省略!!!
(2)(parameter list)->return type{function body}与其他的普通函数一样,但是lambda必须使用尾置返回类型。
(parameter list)的函数形参为空时,可以省略!!!
return type函数返回类型可以推断时,可以省略!!!
eg:
std::vector<int>vec(1,3,23,43);
std::transform(vec.begin(),vec.end(),vec.begin(),
[](int i){return i <0 ? -i :i});
transform函数接受三个迭代器和一个可调用对象,此例的可调用对象为lambda表达式。前两个迭代器表示输入序列,第三个迭代器表示目的位置。算法对输入序列中每个元素调用lambda表达式,并将结果写到目的迭代器位置。lambda表达式形参i的实参为调用它对象的容器中每个元素。
{function body}函数体{}不能省略!!!
demo如下:
#include <iostream>
#include <string>
#include <functional>
int call_exefunc(int a,int b)
{
std::cout << a - b << std::endl;
return 0;
}
using funType1 = std::function<int(int,int)>;
void call_func(funType1 pf)
{
pf(2,3);
}
class DataCheck
{
public:
void printF(){std::cout << "hello DataCheck " << std::endl;}
};
class SaleItem
{
public:
//1 如果有多个构造函数时,仍需要编译器默认的构造函数,则可以在声明时,在()后面加default,表示使用系统生成的默认构造函数。
//1 这种在声明时,写=default,表示构造函数为类的内联函数;如果不想用内联函数,在声明和定义分开写。
//1 默认的构造函数的形参为空。
SaleItem()=default;
//2 拷贝构造函数用于类类型对象的初始化操作。如果不定义会默认生成。
SaleItem(const SaleItem&);
void PrintMem(){std::cout << "m_n1 " << m_n1 << std::endl;std::cout << "m_n2 " << m_n2 << std::endl;}
int m_n1=10;
int m_n2 = 1;;
};
SaleItem::SaleItem(const SaleItem& org)
{
m_n1 = org.m_n1+2;
m_n2 = org.m_n2 *2;
}
int main(int argc,char** argv)
{
//回调函数与using and std::function的函数模板类型对象
std::cout << "exe name is " << argv[0] << std::endl;
call_func(call_exefunc);
std::function<int()> fun1 = []{return 3;};
std::cout << "fun1 " << fun1() << std::endl;
std::function<int(int,int)> fun2 = call_exefunc;
std::cout << fun2(3,1) << std::endl;
std::function<int(int,int)> fun3 = std::bind(call_exefunc,std::placeholders::_1,std::placeholders::_2);
std::cout << fun3(3,1) << std::endl;
//std::bind在绑定普通函数时跟其他的普通函数的函数指针方法一致,std::bind可以绑定类成员函数,这个是普通函数代替不了的。
DataCheck objData;
std::function<void()>fun4 = std::bind(&DataCheck::printF,&objData);
fun4();
SaleItem objSale;
std::function<void()> fun5 = std::bind(&SaleItem::PrintMem,&objSale);
fun5();
SaleItem obj1;
SaleItem obj2(obj1); //拷贝构造函---将类对象作为另一个函数的形参
obj2.PrintMem();
SaleItem obj3 = obj1; //拷贝构造函----使用=
obj3.PrintMem();
return 0;
}