tags:

views:

720

answers:

6

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!

+5  A: 

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.

Eric Petroelje
+1  A: 

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

Nemanja Trifunovic
There is no real function pointer _variable_ defined here, so from an inlining view, I'd say they are the same.
Marco van de Voort
No, they're not the same from an inlining point of view. Think about the types that for_each is instantiated with. In the function pointer case, it is instantiated with an argument of type void (*)(int). In the second case, with an argument of type functor. The former says nothing about which function is called, so it can't be easily inlined. The latter means that the compiler can trivially deduce that the functino to call is functor::operator()()
jalf
Taking a pointer to a function prevents the compiler from inlining it. Always.
Vincent Robert
@Vincent: “always” is a strong qualifier, and easily proven wrong, as done by MSN in his answer. However, until quite recently you would have been right.
Konrad Rudolph
+7  A: 

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.

Doug T.
+1  A: 

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

Martin Beckett
+14  A: 

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.

Konrad Rudolph
In what sense do they play nicer with the STL algorithms?
Gab Royer
See my update. Basically, it's argument binding that's the problem here.
Konrad Rudolph
Doesn't std::ptr_fun take care of how to use a function pointer with std::bindXXX?
MSN
MSN: yes, of course – that’s my whole point, though: you need an additional shim to make it work.
Konrad Rudolph
+5  A: 

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].

MSN
Very insightful thanks!
Gab Royer