仿函数的用法
在C语言时期,如果想要实现回调函数或者是函数参数需要传入函数,通常是用的函数指针。而在C++中,我们一般用仿函数来平替。
仿函数,又叫函数对象。虽然名字叫仿函数,但本质上就是一个重载了 operator() 的类,这个类的核心内容就是这个 operator() 方法,写法实例如下:
// 仿函数的类
class Showme
{
public:
void operator()(string name = "xiaoming")
{
cout << "我的名字是 " << name << endl;
}
};
// 测试的类
template<typename Show>
class test
{
public:
void fun()
{
show();
show("wugang");
}
private:
Show show;
};
int main()
{
// 仿函数做函数参数
Showme show;
show();
show("lihua");
cout << "****************" << endl;
// 仿函数做类的模板参数
test<Showme> myshow;
myshow.fun();
return 0;
}
可以看到,当我们用仿函数的类定义出了对象之后,那么这个对象在用法上就相当于是一个函数了,其写法已经和函数调用无异了,这也是为什么这个东西叫“仿函数”的原因之一。
其实单从用法角度来讲,函数对象就相当于函数指针。只不过综合来讲,仿函数的优势更大:
- 灵活性和可定制性: 函数对象是类的实例,因此可以包含某些状态信息(通过成员变量),并且可以定义操作符重载,使得函数对象可以像普通函数一样调用。这意味着可以实现更灵活和可定制的行为。
- 性能优势: 一些编译器可以对函数对象进行内联优化,因为函数对象是类的实例,而函数指针则可能无法被内联。内联可以减少函数调用的开销,从而提高性能。
- 类型安全: 函数对象是类型安全的,因为它们是类的实例。编译器可以在编译时检查函数对象的类型,避免了在运行时可能发生的类型错误。
- 可组合性: 函数对象可以被组合起来形成更复杂的操作,这通常通过函数对象适配器(如std::bind、std::function等)来实现。这种组合性使得函数对象在STL中被广泛使用,例如在算法中可以传递不同的函数对象来实现不同的行为。
- 更多的操作符重载: 函数对象可以重载多个操作符,而函数指针只能代表一个函数。这意味着函数对象可以模拟更复杂的操作,而不仅仅局限于函数调用。
内建仿函数
STL内建了一些函数对象,可大致分为算数类函数对象,关系运算类函数对象,逻辑运算类函数对象这3类。这些函数对象用法和一般函数对象完全一致,只是这些常用的函数对象都被封装在库中了,使我们不用再自己写了,提高了编码效率。至于具体有哪些内建函数对象见下图: