Ara*_*raK 6 c++ pointers reference
当我读到这个问题的litb回答时,我了解到通过引用传递数组允许我们获得它的大小.我只是玩了一点代码,并尝试通过引用传递一个"函数",并且令人惊讶地(至少对我来说),这段代码编译:
void execute( void (&func)() ) // func is passed by reference!
{
func();
}
Run Code Online (Sandbox Code Playgroud)
最后一个函数和这个函数之间有什么区别:
void execute( void (*func)() ) // func is passed by pointer!
{
func();
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用VC2008,它在每种情况下产生不同的输出.奇怪的是,在函数指针的情况下,编译器会更好地优化代码:
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)
}
Run Code Online (Sandbox Code Playgroud)
必须有区别,虽然我没有看到,对吧?
注意:代码是使用VC2008编译的,/O2并且已/Ot打开.
编辑::我真的很感兴趣的函数引用和函数指针之间的任何区别.我检查了生成的汇编代码,看看它是如何在每种情况下进行翻译的.
对于语言差异(仅保留下面的函数声明,因为这才是重要的)
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
}
Run Code Online (Sandbox Code Playgroud)
它不起作用,因为它需要一个函数,而不是函数指针。出于同样的原因,数组答案拒绝指针,这也拒绝指针。您必须直接传递“g”。
对于模板来说,这也很重要
template<typename T>
void execute(T &t) { T u = t; u(); }
template<typename T>
void execute(T t) { T u = t; u(); }
Run Code Online (Sandbox Code Playgroud)
这两者非常不同。如果您像上面那样调用它execute(g);,那么第一个将尝试声明一个函数并使用t(参考g)初始化它。生成的函数看起来像这样
void execute(void(&t)()) { void u() = t; u(); }
Run Code Online (Sandbox Code Playgroud)
现在您可以初始化函数的引用和指针,但当然不能初始化函数本身。在第二个定义中,T将通过模板参数推导将其推导为函数指针类型,并且传递函数将其隐式转换为该指针参数类型。所以一切都会顺利。
我不知道为什么 MSVC 对内联的处理方式不同 - 但我也怀疑这是因为函数引用出现得很少。