Function pointer vs Function reference

Functions and function references (i.e. id-expressions of those types) decay into function pointers almost immediately, so the expressions func and f_ref actually become function pointers in your case. You can also call (***func)(5) and (******f_ref)(6) if you like.

It may be preferable to use function references in cases where you want the &-operator to work as though it had been applied to the function itself, e.g. &func is the same as &f_ref, but &f_ptr is something else.


See here.

The address-of operator acts like you would expect, as it points to a function but cannot be assigned. Functions are converted to function pointers when used as rvalues, which means you can dereference a function pointer any number of times and get the same function pointer back.


As there are good answers from other people here, there is no answer explaining why f_ptr = &&func; does not work. When you apply the addressof operator & to a variable/function, you get its address. The adress itself is an r-value/a temporary variable. You cannot take the address of a temporary.

But it seems that there is a type error. The message implicit conversion from void* is very compiler specific for this code. I guess you are using GCC/Clang. GCC/Clang offers the ability to take the address of labels like &&label. The resulting value is of type void*. Other compilers will output something like cannot take address of temporary or invalid syntax. When using these compilers this kind of error could have been hidden without any warning in special circumstances:

int main() {
    int foo = 42;
    foo:;
    void* a = &foo; // take the address of a variable/function
    void* b = &&foo; // take the address of a label

    std::cout << *(int*)a << '\n';
    goto *b;
};

But who would name everything the same?


"Why function pointer does not require dereferencing?"

Because the function identifier itself is actually a pointer to the function already:

4.3 Function-to-pointer conversion
§1 An lvalue of function type T can be converted to an rvalue of type “pointer to T.” The result is a pointer to the function.

"Why dereferencing a function reference doesn't result in an error?"

Basically you can look at defining a reference as defining an alias (alternative name). Even in the standard in 8.3.2 References in part addressing creating a reference to an object, you will find:
"a reference can be thought of as a name of an object."

So when you define a reference:

void (& f_ref)(int) = func;

it gives you the ability to use f_ref almost everywhere where it would be possible to use func, which is the reason why:

f_ref(1);
(*f_ref)(4);

works exactly the same way as using the func directly:

func(1);
(*func)(4);