Using STL algorithms, is it better to pass a function pointer or a functor?

拥有回忆 提交于 2019-12-09 15:25:17

问题


Which of these 2 methods is better and why?

Method 1:

void fun(int i) {
  //do stuff
}

...
for_each(a.begin(), a.end(), fun);

Method 2:

class functor {
public:
  void operator()(int i);
};

...
for_each(a.begin(), a.end(), functor());

Edit: Should have formulated it this way, in what situation is one of the above method preferable to the other?

Thanks a lot!


回答1:


Functors may (and will) be trivially inlined – this isn't done for regular function pointers.

Thus, functors have a real performance benefit which may be huge in tight loops. Furthermore, functors are generally more easily composable and in particuler play nicer with the STL: std::bindx doesn't work on function pointers, for instance.

I hate how they clutter the code but given all the advantages, I'd prefer them over function pointers any time.




回答2:


To clear up a misconception of what a compiler can inline, a good enough compiler can inline function pointers. It can just inline function objects more easily since there is more static information available. E.g., a pointer to a function that takes no parameters and returns a bool is of type bool (*)(), while a functor has an explicit type, namely, the functor, and the template instantiation can statically call the functor operator, rather than having to call through a function pointer.

In practice, though, it's mainly a matter of giving the compiler enough information to optimize effectively.

For example, Visual C++ 2008, given the following code with full optimizations:

#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;
}

inlines both std::for_each calls completely. Incidentally, on the PC, the first for_each has an unnecessary lea ecx, [ecx].




回答3:


One big advantage of a function object over a function pointer is that you can more easily bind up some arguments at function object construction.

An example of a functor that might do this would be

  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));

This "binding" of arguments can be done quite nicely with boost::bind and boost::function if boost is available to you.




回答4:


My opinion - #1 is better, because it's simpler.

Just because something can be an object, doesn't mean it should be one. I'm sure there are cases where the functor makes sense, but in most cases there's probably no need for it.




回答5:


A functor can be more easily inlined, so it may be a factor to consider when performance is important.




回答6:


#1 is simpler to declare the function
while #2 the functor looks more like a function call.

(Sometime you have to despair of c++ syntax)



来源:https://stackoverflow.com/questions/1027610/using-stl-algorithms-is-it-better-to-pass-a-function-pointer-or-a-functor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!