通过引用传递并使用引用运算符

joe*_*_04 0 c++ parameters reference

在我的第一堂 C++ 编程课中,我们没有学习引用运算符在将变量作为引用传递时做什么,我们只是了解到在形参列表中使用引用运算符意味着该变量直接更改 main 中相应的变量。但现在,我正在大学上第二堂编程课,我正试图了解到底发生了什么。考虑这段代码:

#include <iostream>
using namespace std;

void Reference(int & Cool, int Neato);

int main()
{
    int Awesome=10;
    int *P = & Awesome;
    int Neat=20;

    Reference(Awesome, Neat);

    cout << *P << endl;
}

void Reference(int & Cool, int Neato)
{
    ++Cool;
}
Run Code Online (Sandbox Code Playgroud)

第一次使用引用运算符时,我将变量 Awesome 的地址赋予指针 *P。这对我来说完全有道理。我得到了 P 的值,该值是 Awesome 的地址。之后,我通过引用将 Awesome 传递给函数,我明白发生了什么,但是编译器如何读取它?

我使用变量 Neat 作为我所要求的示例。Neat 是按值传递的,所以我假设编译将其视为:

Neato = Neat;
Run Code Online (Sandbox Code Playgroud)

但是编译器如何读取通过引用传递 Awesome 的情况呢?按照与上面相同的逻辑,我假设:

& Cool = Awesome;
Run Code Online (Sandbox Code Playgroud)

但从语法和逻辑上来说,这根本没有意义。特别是与第一个例子相比(这是完全有道理的):

int *Pointer = & Awesome;
Run Code Online (Sandbox Code Playgroud)

所以,我只是想弄清楚究竟发生了什么。我知道通过引用传递的变量在其对应的函数变量发生变化时直接被改变,但是后台发生了什么?

Sam*_*hik 5

首先,让我们了解一些基本规则。与您的问题没有直接关系,但需要建立这些基本规则。

“&”运算符是重载的,在两个不同的内容中表示两个不同的事物。

int foo=0;

int *bar=&foo;
Run Code Online (Sandbox Code Playgroud)

这里,“&”是地址运算符。这意味着获取其他对象的地址,这成为指向该对象的指针。

void foo(int &bar);
Run Code Online (Sandbox Code Playgroud)

这里,“&”声明了一个引用。这里,“&”表示引用声明。这是一个有点微妙的概念,但区别很重要。

现在,抛开这个问题,回答你的问题:

从某种意义上说,引用实际上是一个“隐藏指针”。为了创建引用,编译器会生成与实现地址运算符时相同的代码,并且引用在内部只是一个指针。

void foo(int &);

// ...

int bar=0;

foo(bar);
Run Code Online (Sandbox Code Playgroud)

这可以被认为类似于:

void foo(int *);

// ...

int bar=0;

foo(&bar);
Run Code Online (Sandbox Code Playgroud)

这在逻辑上是等价的。

现在,回答第二部分。任何时候使用引用时,都会从解引用运算符“*”运算符开始,将引用实际应用于内部指针:

int foo(int &bar)
{
    int foobar=bar;
Run Code Online (Sandbox Code Playgroud)

这类似于:

int foo(int *bar)
{
    int foobar=*bar;
Run Code Online (Sandbox Code Playgroud)

综上所述:

A)当创建一个新的引用时,就好像对引用的对象使用了地址运算符。

B) 当使用现有引用时,就好像在指向所引用对象的实际指针上使用取消引用运算符一样。

这应该可以帮助您理解传递引用时会发生什么。