函数对象是就是一个类对象,由于重载了调用运算符()而具有了类似函数的调用形式。通常使用函数对象来实现某种形式的回调,和传统的用函数指针实现的回调相比,函数对象有以下优点:
- 能在多次调用之间保存数据。由于函数对象可以有成员变量,很容易在多次调用之间保存数据。而常规函数则必须借助于静态局部变量或全局变量,显得很不自然。
- 运行效率更高。对使用函数指针进行的调用,编译器由于不能确定实际调用的函数的名称,生成的机器指令只是一种间接调用;而对使用函数对象进行的调用,编译器知道函数的名称(即重载调用运算符的那个函数),因此可以生成直接调用的机器指令,而且可以把调用运算符内联化来获得进一步效率提升,而把一个通过指针传递的函数内联化是非常困难的。
- 更灵活。可以在函数对象里提供一些操作,完成初始化和对有关数据的提取工作等。
template<typename T>
class BPFCImpl : public unary_function<T, void> {
private:
Widget w;
int x;
...
virtual ~BPFCImpl();
virtual void operator()(const T& val) const;
friend class BPFC<T>;
};
template<typename T>
class BPFC : public unary_function<T, void> {
private:
shared_ptr<BPFCImpl<T> > pImpl;
public:
void operator()(const T& val) const
{
pImpl->operator() (val);
}
...
};
boost::thread thrd(bind(f, 1))//假设以1为实参运行f
再如:想对vector<int> v 中的每个元素做个处理,而负责处理的函数是类 A 成员函数 void A::f(int i) ,这时就可写:
A a;
for_each(v.begin(), v.end(), bind(&A::f, &a, _1));
bind(f, _1, _1);//生成带一个参数的函数对象,以这个参数作为f的第一和第二个实参来调用f
bind(f, _1, _1+1, _2);//生成带两个参数的函数对象,以第一个参数作为f的第一个实参,第一个参数加1作为f的第二个实参,第二个参数作为f的第三个实参来调用f