代码之家  ›  专栏  ›  技术社区  ›  Khaled Alshaya

在这种情况下,有人能解释一下“引用”和“指针”的区别吗?

  •  6
  • Khaled Alshaya  · 技术社区  · 15 年前

    当我阅读 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 打开。


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

    4 回复  |  直到 13 年前
        1
  •  3
  •   Johannes Schaub - litb    14 年前

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

    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
    }
    

    它不工作,因为它需要一个函数,而不是函数指针。与数组应答拒绝指针的原因相同,数组应答也拒绝指针。你必须直接通过“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对它们的内联处理方式不同——但我也怀疑这是因为函数引用很少出现。

        2
  •  3
  •   Pete Kirkham    15 年前

    这不是一个常见的习语,所以可能只是因为vs团队没有添加一个规则来优化它。

        3
  •  3
  •   Kirill V. Lyadvinsky    15 年前

    我认为这是因为C++标准4.3:

    函数类型t的左值可以转换为类型_指向t的指针的右值。结果是指向 功能。

        4
  •  -2
  •   thkala jaxb    13 年前

    引用(&)和指针(*)的区别在于,引用提供变量的地址或位置,指针指向存储在其中的地址在内存中的位置。

    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.
    

    我们可以得出结论(&variable)具有该内存位置的地址,*anyname指向存储在其内存中的地址…