When I read litb answer to this question, I learned that passing an array by reference allows us to obtain its size. I just played little bit with code, and tried to pass a "function" by reference and surprisingly (at least for me), this code compiles:
void execute( void (&func)() ) // func is passed by reference!
{
func();
}
Is there any difference between the last function, and this one:
void execute( void (*func)() ) // func is passed by pointer!
{
func();
}
I tried it using VC2008, and it produces different output in each case. The strange thing is that the compiler optimizes the code better in case of a function pointer:
void print()
{
std::cout << "Hello References!";
}
void execute( void (&func)() ) // optimized
{
func();
}
int main()
{
00291020 call print (291000h)
}
=========================================
// In this case, the compiler removes all function calls in the code!
void print() // optimized!
{
std::cout << "Hello Pointers!";
}
void execute( void (*func)() ) // optimized
{
func();
}
int main()
{
002F1005 push offset string "Hello References!" (2F2124h)
002F100A push eax
002F100B call std::operator<<<std::char_traits<char> > (2F1150h)
}
There has to be a difference, although I don't see it, right?
Note: the code was compiled using VC2008, with /O2
and /Ot
turned on.
EDIT:: I am really interested about any difference between function references and function pointers. I examined the produced assembly code just to see how it is translated in each case.
Best Answer
For the language difference (keeping only the function declarations below, since that's what's important only)
It doesn't work, because it wants a function, not a function pointer. For the same reason that array answer rejects a pointer, this rejects a pointer too. You have to pass "g" directly.
For templates, it matters too
Those two are very different from one another. If you call it with
execute(g);
like above, then the first will try to declare a function and initialize it witht
(reference tog
). The generated function would look like thisNow you can initialize references and pointers to functions, but of course not functions itself. In the second definition,
T
will be deduced to a function pointer type by template argument deduction, and passing a function will convert it to that pointer parameter type implicitly. So everything will go fine.I don't know why MSVC treats them differently for inlining - but i also suspect it's because function references appear more seldom.