问题
In the code below, function-pointer and what i considered as "function-reference" seems to have identical semantics:
#include <iostream>
using std::cout;
void func(int a) {
cout << "Hello" << a << '\n';
}
void func2(int a) {
cout << "Hi" << a << '\n';
}
int main() {
void (& f_ref)(int) = func;
void (* f_ptr)(int) = func;
// what i expected to be, and is, correct:
f_ref(1);
(*f_ptr)(2);
// what i expected to be, and is not, wrong:
(*f_ref)(4); // i even added more stars here like (****f_ref)(4)
f_ptr(3); // everything just works!
// all 4 statements above works just fine
// the only difference i found, as one would expect:
// f_ref = func2; // ERROR: read-only reference
f_ptr = func2; // works fine!
f_ptr(5);
return 0;
}
I used gcc version 4.7.2 in Fedora/Linux
UPDATE
My questions are:
Why function pointer does not require dereferencing?Why dereferencing a function reference doesn't result in an error?- Is(Are) there any situation(s) where I must use one over the other?
- Why
f_ptr = &func;works? Since func should be decayed into a pointer?
Whilef_ptr = &&func;doesn't work (implicit conversion fromvoid *)
回答1:
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.
回答2:
"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 typeTcan be converted to an rvalue of type “pointer toT.” 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);
回答3:
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.
回答4:
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?
来源:https://stackoverflow.com/questions/19200513/function-pointer-vs-function-reference