当我读到litb answer to this question ,我了解到通过引用传递数组可以让我们获得它的大小。我只是玩了一点代码,并尝试通过引用传递一个“函数”,令人惊讶的是(至少对我而言),这段代码编译:
void execute( void (&func)() ) // func is passed by reference!
{
func();
}
上一个函数和这个函数有什么区别吗:
void execute( void (*func)() ) // func is passed by pointer!
{
func();
}
我用 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)
}
肯定是有区别的,虽然我没看到,对吧?
注意:代码是用VC2008编译的,/O2
和/Ot
打开
EDIT:: 我对函数引用和函数指针之间的任何区别非常感兴趣。我检查了生成的汇编代码,只是为了了解它在每种情况下是如何翻译的。
最佳答案
对于语言差异(只保留下面的函数声明,因为那才是重要的)
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
}
它不起作用,因为它需要一个函数,而不是函数指针。出于与数组 answer 拒绝指针相同的原因,这也拒绝指针。你必须直接传递“g”。
对于模板,它也很重要
template<typename T>
void execute(T &t) { T u = t; u(); }
template<typename T>
void execute(T t) { T u = t; u(); }
这两者非常不同。如果你像上面那样用 execute(g);
调用它,那么第一个将尝试声明一个函数并用 t
初始化它(引用 g
)。生成的函数看起来像这样
void execute(void(&t)()) { void u() = t; u(); }
现在您可以初始化函数的引用和指针,但当然不能初始化函数本身。在第二个定义中,T
将通过模板参数推导推导为函数指针类型,传递函数会将其隐式转换为该指针参数类型。所以一切都会好起来的。
我不知道为什么 MSVC 以不同方式对待它们以进行内联 - 但我也怀疑这是因为函数引用很少出现。
关于c++ - 在这种情况下,有人可以解释 "reference"和 "pointer"之间的区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1516958/