在这种情况下,有人可以解释"参考"和"指针"之间的区别吗?

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打开.


编辑::我真的很感兴趣的函数引用和函数指针之间的任何区别.我检查了生成的汇编代码,看看它是如何在每种情况下进行翻译的.

Joh*_*itb 3

对于语言差异(仅保留下面的函数声明,因为这才是重要的)

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 对内联的处理方式不同 - 但我也怀疑这是因为函数引用出现得很少。