11

In C++ Standard Template Library, there's a 'functional' part, in which many classes have overloaded their () operator.

Does it bring any convenience to use functions as objects in C++?

Why can't we just use function pointer instead? Any examples?

Alok Save
  • 202,538
  • 53
  • 430
  • 533
Determinant
  • 3,886
  • 7
  • 31
  • 47
  • 1
    Possible duplicate of [C++ Functors - and their uses](http://stackoverflow.com/questions/356950/c-functors-and-their-uses). – Jesse Good Mar 09 '12 at 02:53

4 Answers4

10

Ofcourse, One can always use Function pointers instead of Function Objects, However there are certain advantages which function objects provide over function pointers, namely:

  • Better Performance:

One of the most distinct and important advantage is they are more likely to yield better performance. In case of function objects more details are available at compile time so that the compiler can accurately determine and hence inline the function to be called unlike in case of function pointers where the derefencing of the pointer makes it difficult for the compiler to determine the actual function that will be called.

  • Function objects are Smart functions:

Function objects may have other member functions and attributes.This means that function objects have a state. In fact, the same function, represented by a function object, may have different states at the same time. This is not possible for ordinary functions. Another advantage of function objects is that you can initialize them at runtime before you use/call them.

  • Power of Generic programming:

Ordinary functions can have different types only when their signatures differ. However, function objects can have different types even when their signatures are the same. In fact, each functional behavior defined by a function object has its own type. This is a significant improvement for generic programming using templates because one can pass functional behavior as a template parameter.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
4

Why can't we just use function pointer instead? Any examples?

Using C style function pointer cannot leverage the advantage of inlining. Function pointer typically requires an additional indirection for lookup.
However, if operator () is overloaded then it's very easy for compiler to inline the code and save an extra call, so increase in performance.

The other advantage of overloaded operator () is that, one can design a function which implicitly considers the function object as argument; no need to pass it as a separate function. Lesser the hand coded program, lesser the bugs and better readability.

This question from Bjarne Stroustrup (C++ inventor) webpage explains that aspect nicely.

C++ Standard (Template) Library uses functional programming with overloaded operator (), if it's needed.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Some compilers will actually remove the indirect call and inline through a function pointer, when the value of the function pointer is constant and known at compile-time. – Jonathan Wakely Jun 22 '12 at 17:56
3

> Does it bring any convenience to use functions as objects in C++?

Yes: The C++ template mechanism allows all other C/C++ programming styles (C style and OOP style, see below).

> Why can't we just use function pointer instead? Any examples?

But we can: A simple C function pointer is an object with a well defined operator(), too. If we design a library, we do not want to force anyone to use that C pointer style if not desired. It is usually as undesired as forcing everything/everyone to be in/use OOP style; see below.


From C-programmers and functional programmers views, OOP not only tends to be slower but more verbose and in most cases to be the wrong direction of abstraction ("information" is not and should not be an "object"). Because of that, people tend to be confused whenever the word "object" is used in other contexts.

In C++, anything with the desired properties can be seen as an object. In this case, a simple C function pointer is an object, too. This does not imply that OOP paradigms are used when not desired; it is just a proper way to use the template mechanism.


To understand the performance differences, compare the programming(-language) styles/paradigms and their possible optimisations:

C style:

  • Function pointer with its closure ("this" in OOP, pointer to some structure) as first parameter.
  • To call the function, the address of the function needs to be accessed first.
  • That is 1 indirection; no inlining possible.

C++ (and Java) OOP style:

  • Reference to an object derived from a class with virtual functions.
  • Reference is 1st pointer.
  • Pointer to virtual-table is 2nd pointer.
  • Function pointer in virtual-table is 3rd pointer.
  • That are 3 indirections; no inlining possible.

C++ template style:

  • Copy of an object with () function.
  • No virtual-table since the type of that object is known at compile time.
  • The address of the function is known at compile time.
  • That are 0 indirections; inlining possible.

The C++ templates are versatile enough to allow the other two styles above, and in the case of inlining they can even outperform…

compiled functional languages: (excluding JVM and Javascript as target platforms because of missing "proper tail calls")

  • Function pointer and reference to its closure in machine registers.
  • It is usually no function "call" but a GOTO like jump.
  • Functions do not need the stack, no address to jump back, no parameters nor local variables on the stack.
  • Functions have their garbage collectable closure(s) containing parameters and a pointer to the next function to be called.
  • For the CPU to predict the jump, the address of the function needs to be loaded to a register as early as possible.
  • That is 1 indirection with possible jump prediction; everything is nearly as fast as inlined.
comonad
  • 5,134
  • 2
  • 33
  • 31
  • I am not sure how this answers any of the questions asked by the OP. – Alok Save Mar 09 '12 at 17:24
  • @Als: I've edited my answer to match the question directly. Most of my answer contains what I think is the indirect asked information. – comonad Mar 09 '12 at 19:00
2

The main difference is that function objects are more powerful than plain function pointers as they can hold state. Most algorithms take templates functions rather than plain function pointers, which enable the use of powerful constructs as binders that call functions with different signatures by filling extra arguments with values stored on the functor, or the newer lambdas in C++11. Once the algorithms are designed to take functors it just makes sense to provide a set of predefined generic function objects in the library.

Aside from that there are potential advantages in that in most cases those functors are simple classes for which the compiler has the full definition and can perform inlining of the function calls improving performance. This is the reason why std::sort can be much faster than qsort from the C library.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489