30

What is the difference between using functors and function pointers. For example

  //Functor
  struct add_x
  {
    int x;
    add_x(int y):x(y){}
    int operator()(int y)
    {
       return x+y;
    }
  };
  //Function
  int (func)(int x)
  {
     return ++x;
  }
  std::vector<int> vec();
  //fill vec with 1 2 3 4 5
  int (*f)(int) = func;//Function pointer
  std::transform(vec.begin(),vec.end(),f); //approach 1
  std::transform(vec.begin(),vec.end(),add_x(1)); //approach 2

Both approaches work but i am sure there will be cases where one is preferred(or possible) over other.

Gaurav Sehgal
  • 7,422
  • 2
  • 18
  • 34
  • 1
    In your example, you could replace `add_x(1)` by `add_x(2)`. To get the same change with the function pointer, you would have to change that function. – Magnus Hoff Jun 04 '16 at 21:47
  • as pointed out in the [answer to this question](http://stackoverflow.com/questions/356950/c-functors-and-their-uses) functors can contain state. You could, for example, write a functor that returns x+1 the first time it is called, x+2 the second time, and so on. You can of course achieve the same by using a bind-function to let the compiler turn a function with two arguments into a functor with one argument and external state. – a.peganz Jun 04 '16 at 21:51
  • Possible duplicate of [Why use functors over functions?](https://stackoverflow.com/questions/6451866/why-use-functors-over-functions) – 463035818_is_not_an_ai Aug 07 '17 at 17:54

2 Answers2

33

For one, the functor can contain internal state; a state that is valid for this invocation of the function object only. You could add static variables to your function, but those would be used for any invocation of the function.

Second, the compiler can inline calls to the functor; it cannot do the same for a function pointer. This is why C++ std::sort() beats the crap out of C qsort() performance-wise.

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • 2
    Can you please explain a bit more about why function pointer call cannot be inline... – Gaurav Sehgal Jun 04 '16 at 22:01
  • 4
    @GauravSehgal: Allow me to point you to [this answer](http://stackoverflow.com/questions/2225643). – DevSolar Jun 04 '16 at 22:29
  • 2
    Inlining, roughly speaking, relies definitions of callers and callees being visible to the compiler. Passing function pointers means the compiler is less likely to have the information it needs to inline (e.g. `qsort()` is built without visibility of actual functions passed to it). Stylistically, functors are often used in circumstances where the compiler has complete visibility of their definition, so it can inline. Inlining of a functor can be prevented if the compiler does not have complete visibility of definitions (of the functor's `operator()`, etc) that are in another compilation unit. – Peter Jun 04 '16 at 22:30
1

functors can be even used to emulate lambda expressions (if you have to use an older compiler before C++11/C++14) to a certain extent, because they can have individual state (e.g. as member variables).

struct A {
   int x; // state member can even be made private! Instance per functor possible
   int operator()(int y) { return x+y }
};

or as lambda

auto lambda = [&x](int y) { return x+y };

function pointers can only get arguments, but are stateless, unless they access any global variables (which is really bad design and dangerous).

// global scope, anyone can accidentally manipulate and not thread-safe here, only one global instance possible!
inx x; 
int (func)(int y) { return x+y };
cwschmidt
  • 1,194
  • 11
  • 17
  • 1
    A bit backwards, because C++ had functors *before* lambdas. ;-) – DevSolar Jun 04 '16 at 22:27
  • 4
    @DevSolar: The OP particularly asked about functors. As I said, you can emulate lambdas by functors (e.g. if you have an older compiler before C++11/C++14). Stating this, obviously implies that functors are older than lambdas. – cwschmidt Jun 04 '16 at 22:43