82

Whats the difference between std::function<> and a standard function pointer?

that is:

typedef std::function<int(int)> FUNCTION;
typedef int (*fn)(int);

Are they effectively the same thing?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
aCuria
  • 6,935
  • 14
  • 53
  • 89

4 Answers4

65

A function pointer is the address of an actual function defined in C++. An std::function is a wrapper that can hold any type of callable object (objects that can be used like functions).

struct FooFunctor
{
    void operator()(int i) {
        std::cout << i;
    }
};

// Since `FooFunctor` defines `operator()`, it can be used as a function
FooFunctor func;
std::function<void (int)> f(func);

Here, std::function allows you to abstract away exactly what kind of callable object it is you are dealing with — you don't know it's FooFunctor, you just know that it returns void and has one int parameter.

A real-world example where this abstraction is useful is when you are using C++ together with another scripting language. You might want to design an interface that can deal with both functions defined in C++, as well as functions defined in the scripting language, in a generic way.

Edit: Binding

Alongside std::function, you will also find std::bind. These two are very powerful tools when used together.

void func(int a, int b) {
    // Do something important
}

// Consider the case when you want one of the parameters of `func` to be fixed
// You can used `std::bind` to set a fixed value for a parameter; `bind` will
// return a function-like object that you can place inside of `std::function`.

std::function<void (int)> f = std::bind(func, _1, 5); 

In that example, the function object returned by bind takes the first parameter, _1, and passes it to func as the a parameter, and sets b to be the constant 5.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Paul Manta
  • 30,618
  • 31
  • 128
  • 208
  • 1
    @makar It's the identifier used by `std::bind` to refer to the first argument of the resulting function. It's a bit like: `void bound(int _1) { func(_1, 5); }`. – Paul Manta May 09 '13 at 16:42
  • [The link here](http://stackoverflow.com/questions/25848690/should-i-use-stdfunction-or-a-function-pointer-in-c) mentioned another different between function pointer and std::function: The lambda capture is unable to be used in function pointer.So if you try to use lambda `[&](int a, int b){/*blah*/}`, or `[=](int a, int b){/*blah*/}`, you will have a compile error. The only valid format is `[](int a, int b){/*blah*/}` – r0n9 Jul 24 '15 at 02:30
  • 1
    Using bind is no longer recommended. We have lambda's, which are a nicer mechanism. While `bind` is not deprecated - I wouldn't it make it look like I were promoting its use. – einpoklum Oct 05 '17 at 11:08
  • `std::function` may be more convenient but it will cost you some performance over the raw function pointer ,when used with `std::bind`. – Balan Narcis Feb 09 '20 at 11:47
  • The last example with std::bind looks a lot like partial application in functional programming. Didn't know such a thing was possible in C++. – alexpanter Apr 23 '20 at 21:51
  • ICYDK '_1' is defined in the std::placeholders namespace (I didn't know that at first, just looked it up). – John Colvin Sep 07 '22 at 16:56
  • For clarity) `std::function` `f(func);` or `f{func};` or `f=func;` all works. – starriet Jun 04 '23 at 13:18
60

They are not the same at all. std::function is a complex, heavy, stateful, near-magic type that can hold any sort of callable entity, while a function pointer is really just a simple pointer. If you can get away with it, you should prefer either naked function pointers or auto-bind/auto-lambda types. Only use std::function if you really need a systematic way of organizing a heterogeneous collection of callable entities, such as functions, functors, capturing lambdas and bind expressions.


Update: A bit of explanation about auto types: Compare the following two functions:

void do_something_1(std::function<void(int)> f, int a) { f(a); }

template <typename F, typename A> void do_something_2(F f, A a) { f(a); }

Now imagine invoking them with a lambda or a bind expression:

do_something_X([foo, &bar](int n){ bar += n*foo; },     12);
do_something_X(std::bind(X::bob, &jim, true, _1, Blue), 13);

The second version with the template is more efficient, because in both cases, the argument F is deduced to the actual, unknowable type of the expression. The first version, with std::function, isn't a template and may look simpler and more deliberate, but it always forces the construction of the std::function object, and quite possibly carries multiple type erasure and virtual dispatch costs.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    This is kinda confusing, mind explaining this further? that is, exactly when to use std::function, and when to use a function pointer. Also, what is a "auto-bind/auto-lambda types" – aCuria Jan 29 '12 at 17:24
  • 4
    @aCuria: If you want to make a container of callable things and you want to put all sorts of mixed types in there, then you *have* to use `std::function` and convert everything. But if you know that you always have genuine free functions, you can just make a container of function pointers. I'll expand on the auto-preference in the actual post in a bit. – Kerrek SB Jan 29 '12 at 17:31
  • Do the calls to do_something in the update need a second parameter (corresponding to the `a` in `do_something_1` and `do_something_2`, or am I completely confused about how they're working? – ben w Jan 29 '12 at 21:57
  • @benw: Not at all, the confusion was entirely on my part - fixed! Thanks :-) – Kerrek SB Jan 29 '12 at 22:28
  • 4
    Function pointers won't work with **lambdas capturing context variables**. If you expect to use lambdas, `std::function` is a better choice. – Jan Včelák Jan 23 '17 at 20:13
  • 1
    @JanVčelák While this is true, the template can handle also lambdas capturing context. So when passing such lambdas you are not limited to use `std::function` but can also use templates. – Roi Danton Mar 13 '18 at 12:13
  • Can I ask why you recommend function pointer over `std::function`? As per core guidelines it is generally more performant. https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rt-fo – Bevan Jones Sep 01 '20 at 14:56
18

A std::function has state. It can hold additional parameters "bound" into it.

These parameters can range from things like other classes, other functions, or even this pointers for member function calls.

The replacement function pointer is not typedef int (*fn)(int);

It is typedef int (*fn)(void*,int);, with the void* reperensting the state that would be hidden in the std::function.

JFMR
  • 23,265
  • 4
  • 52
  • 76
9

No.

One is a function pointer; the other is an object that serves as a wrapper around a function pointer.

They pretty much represent the same thing, but std::function is far more powerful, allowing you to do make bindings and whatnot.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055