【问题标题】:Call by reference in C++在 C++ 中通过引用调用
【发布时间】:2011-01-25 03:00:20
【问题描述】:

实际上通过引用函数在调用中传递了什么?

void foo(int &a,int &b)

当我写作时

foo(p,q)

实际传递给函数的内容。是p和q的地址吗?

【问题讨论】:

  • 我假设您知道引用和指针之间的程序差异,对吧?你是在问它实际上编译成什么?
  • @Peter 既然如此,为什么不简单地看一下发出的代码呢?
  • 我该怎么做。我正在使用 gcc 编译器。
  • gcc -S 会给你asm代码来查看
  • @Peter 检查代码的最简单方法是在调试器中运行它,例如 gdb,或者如果您想要图形界面 Insight 或 DDD。

标签: c++ reference pass-by-reference


【解决方案1】:

实际传递给函数的是引用。命名参数b 成为参数对象q 的同义词。

编译器可能如何实现这一点,即调用者在调用之前将q 的地址放在堆栈或寄存器中,而被调用者使用该值来实现对b 的所有访问。但是将其描述为“实际传递”指针可能会产生误导,因为参数传递是 C++ 语言级别的概念,在该级别上它与传递指针的概念不同。例如,当你传递一个指针时,你可以传递一个空指针,但是当你传递一个引用时,你不能(有效地)。所以说它们是同一件事是错误的。

也就是说,实现编译器的人可能会将其描述为“实际上传递了一个指针”,并且您知道它们的意思。作为比较,如果char 变量在调用约定中占用了 4 字节的栈槽,他们可能会说编译器“实际上是在传递一个 int”。所以这取决于“实际上”应该是什么意思。

【讨论】:

  • “这取决于“实际上”应该是什么意思” ...政治家?
【解决方案2】:

其他答案提到了引用和指针之间的语义差异。

在实践中,我曾经使用过的每个编译器都以相同的方式实现它们——传递引用实际上是在汇编级别传递指针。这在任何标准中都没有规定,只是在实践中无处不在。

问题出现在 SO 之前:What's the low-level difference between a pointer an a reference?

【讨论】:

    【解决方案3】:

    它确实传递了一个引用类型——它有点像地址,但不完全是。实际地址将是一个指针。引用不如指针强大,但可以说更安全。 Wikipedia 很好地描述了指针和引用的区别。

    【讨论】:

      【解决方案4】:

      你传递的是一个引用,它不是一个指针,也不是一个地址——但它是相似的。

      什么是“确切”的参考,并不是一成不变的。该标准没有规定处理参考的机制——只是使用它们的后果。 通常,它们将被实现为指针。

      例子:

      int foo(int& a, int& b) { a = b; }
      
      // Usage
      int x, y;
      foo(x, y);
      

      这可能会生成与以下相同的机器代码:

      int foo(int* a, int* b) { *a = *b; }
      
      // Usage
      int x, y;
      foo(&x, &y);
      

      但不能保证这一点,而且两者并不等同(尽管它们提供相似的功能)。

      当您获取引用的地址时,您将获得与它所引用的对象相同的地址。示例:

      void foo(int& x) { std::cout << &x << std::endl; }
      
      int y;
      std::cout << &y << std::endl;
      foo(); // This will print the same as above.
      

      【讨论】:

        【解决方案5】:

        引用传递的工作方式由您的编译器定义。在任何情况下,它们都作为int&amp; 传递,这是C++ 中的实际类型。试试这个:

        int x = 10;
        int& y = x;
        x = 100;
        

        你认为 y 的值是多少?引用并不完全是指针,而是变量的别名。您的编译器适用于 int&amp; 的相同机制用于传递引用参数。

        给定以下程序:

        void byRef(int& x)
        {
            return;
        }
        
        void byVal(int x)
        {
            return;
        }
        
        void byPtr(int * x)
        {
            return;
        }
        
        int _tmain(int argc, _TCHAR* argv[])
        {
        
            int x = 0;
            byRef(x);
            byVal(x);
            byPtr(&x);
        
            return 0;
        }
        

        byRefbyPtr 调用生成的MSVC90 程序集完全相同,即:

        lea eax, [x]
        push eax
        call byRef ;or byPtr
        add esp, 4
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-11
          • 2011-01-14
          • 2020-08-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多