这两种方法中哪一种更好,为什么?
方法1:
void fun(int i) {
//do stuff
}
...
for_each(a.begin(), a.end(), fun);
方法2:
class functor {
public:
void operator()(int i);
};
...
for_each(a.begin(), a.end(), functor());
编辑:应该用这种方式制定,在什么情况下上述方法之一优于另一种?
非常感谢!
答案 0 :(得分:19)
Functors可以(并且将)简单地内联 - 这不适用于常规函数指针。
因此,仿函数具有真正的性能优势,在紧密循环中可能是巨大的。此外,仿函数通常更易于组合,特别是使用STL更好:std::bind
x
对函数指针不起作用。例如。
我讨厌它们如何使代码混乱,但是考虑到所有优点,我更喜欢它们而不是函数指针。
答案 1 :(得分:11)
为了清除对编译器可以内联的误解,一个足够好的编译器可以内联函数指针。它可以更容易地内联函数对象,因为有更多的静态信息可用。例如,指向不带参数并返回bool的函数的指针是bool(*)()类型,而仿函数有一个显式类型,即仿函数,模板实例化可以静态调用仿函数运算符,而不是而不必通过函数指针调用。
但实际上,主要是为编译器提供足够的信息以便有效地进行优化。
例如,Visual C ++ 2008,给出以下代码并进行完全优化:
#include "stdafx.h"
#include <algorithm>
const char print_me[]= "hello!";
class print_functor
{
public:
void operator()(char c)
{
printf("%c", c);
}
};
void print_function(char c)
{
printf("%c", c);
}
int _tmain(int argc, _TCHAR* argv[])
{
std::for_each(print_me, print_me + sizeof(print_me)/sizeof(print_me[0]), print_functor());
printf("\n");
std::for_each(print_me, print_me + sizeof(print_me)/sizeof(print_me[0]), print_function);
return 0;
}
完全内联std::for_each
次调用。顺便说一下,在PC上,第一个for_each有一个不必要的lea ecx, [ecx]
。
答案 2 :(得分:7)
函数对象相对于函数指针的一大优点是,您可以更容易地在函数对象构造中绑定一些参数。
可能会这样做的仿函数的一个例子是
class multiplyBy
{
private:
int m_whatToMultiplyBy;
public:
multiplyBy(int whatToMultiplyBy) :
m_whatToMultiplyBy(whatToMultiplyBy)
{
}
void operator()(int& i)
{
i = m_whatToMultiplyBy * i;
}
}
...
// double the array
for_each(a.begin(), a.end(), multiplyBy(2));
如果你可以使用提升,那么boost::bind和boost::function可以很好地完成参数的“绑定”。
答案 3 :(得分:6)
我的观点 - #1更好,因为它更简单。
仅仅因为某物可以成为一个物体,并不意味着它应该是一个物体。我确信有些情况下仿函数有意义,但在大多数情况下可能没有必要。
答案 4 :(得分:1)
仿函数可以是more easily inlined,因此在性能很重要时可能需要考虑它。
答案 5 :(得分:1)
#1更容易声明函数
而#2的仿函数看起来更像是一个函数调用。
(有时候你不得不对c ++语法感到绝望)