std::functional
参考文档:cppReference
函数对象(Function objects)是为了,可以像使用函数一样使用对象,而设计的
在C++中,这通过在类中定义opretor()成员函数实现
例如
struct myclass{
int operator()(int a) { return a; }
}object;
int x = object(5);
它们(函数对象)通常作为函数的参数,例如作为谓词或者比较函数传递给标准算法(std::algorithm)
下面介绍<functional>中的函数
这些函数根据提供的参数,创建封装类(wrapper classes)对象
std::bind
std::bind是函数模板,作用是绑定函数参数
template<class Fn, class... Args>
bind(Fn&& fn, Args&&... args);
template<class Ret, class Fn, class... Args> // 带返回值
bind(Fn&& fn, Args&&... args);
fn可以是:函数对象、函数指针、成员指针
bind基于fn,返回一个函数对象,并将参数绑定到args上;
调用时,会使用绑定的参数
每个参数可以绑定到一个值上,也可以绑定到一个占位符上
- 如果绑定到值上,调用该返回的函数对象将一直使用该值作为参数
- 如果绑定到占位符上,调用该函数对象将会转发(forwards)传递给调用的参数(其序号通过占位符指定)
占位符最多10个
调用返回的函数对象,其返回值与fn相同,除非使用第二个模板,指定了返回类型
Ret是唯一一个不能通过传递给此函数的参数,隐式推导出的模板参数
返回对象的类型拥有以下属性:
其函数调用返回值与fn相同,参数绑定到args...(或转发,用于占位符)
该对象是可移动构造的,如果它的所有参数类型都是可拷贝构造的,那么它也是可拷贝构造的。
绑定成员函数
shared_from_this()可以返回对象自身的shared_ptr,前提是该对象是通过智能指针管理的
lambda表达式捕获shared_ptr之后,引用计数+1,保证生命周期(闭包的思想
class Calculator {
public:
int multiply(int a, int b) {
return a * b;
}
};
Calculator calc;
auto func = std::bind(&Calculator::multiply, &calc, 5, std::placeholders::_1);
func的生命周期必须小于calc的生命周期?
lambda捕获智能指针比捕获引用好,因为能保证生命周期
绑定静态成员函数,不需要绑定this指针
小结
占位符的数字表示新函数对象参数的序号(序号需要匹配新对象的参数数量)
通过绑定时的位置顺序和序号,确定相对关系

绑定参数可以改变参数的数量(即提供了默认参数)&顺序
通过绑定this指针,可以将成员函数转成普通函数对象
lambda表达式也可以实现绑定(通过捕获
示例
参数绑定的语义
占位符的语义,使用传入函数对象的实参的位置对应的参数,作为原来可调用对象的参数(根据bind中声明的args列表)
说起来很绕,到底是什么意思呢?
看图
占位符指的就是,传入的对应位置(从1开始数)的实参;使用该实参替换占位符
而原可调用对象的形参与函数对象的args列表一一对应
在此例中,_1会被3替换,_2会被4替换,然后(3,2,a)被传入原可调用对象add()中,var1 = 3, var2 = 2, var3 = a
使用bind原则就是
- args中参数不少于形参列表的参数
- 传入的实参不少于占位符序号

int add(int var1, int var2) { return var1 + var2; }
using namespace std::placeholders;
auto add2 = bind(add, _1, 2); // 将2绑定到var1上
int c = add2(3);
常见错误
args列表少于形参列表

实参数量少于args中占位符序号


浙公网安备 33010602011771号