Could someone please explain the difference between a "reference" and a "pointer" in this case?
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.
For the language difference (keeping only the function declarations below, since that's what's important only)
void execute( void (&func)() );
void g();
int main() {
void (*fp)() = g;
execute(fp); // doesn't work
execute(&g); // doesn't work either
execute(g); // works
}
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
template<typename T>
void execute(T &t) { T u = t; u(); }
template<typename T>
void execute(T t) { T u = t; u(); }
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 with t
(reference to g
). The generated function would look like this
void execute(void(&t)()) { void u() = t; u(); }
Now 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.
It's not as common an idiom, so it might just be that the VS team didn't add a rule to optimise it.
I think it is due to the C++ Standard 4.3:
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.
The difference between a reference(&) and pointer(*) is that the reference provides the address of the variable or the location, and the pointer points to the location in memory of the address stored in it.
int *pointer;
int variable;
pointer = &variable; // assigning the address of variable to pointer
variable = 53; // value of variable
cout << *pointer; // This should output the value of the address where is pointing, in this
// case 53, that is the value of variable to where is pointing.
We can conclude that the (&variable) have the address of that memory location and *anyname points to the address stored in its memory...
精彩评论