C++:变量与引用?

C++: variables vs references?

所以我看到很多关于引用与指针的问题,但我的困惑是变量和引用之间的区别。例如以下代码:

int main() {
    int ival = 1024;
    int &refVal = ival;
    cout << "refVal " << refVal << endl;
    cout << "&refVal " << &refVal << endl;
    cout << "&ival " << &ival << endl;
    return 0;
}

这些是输出:

refVal 1024
&refVal 0x7fff5f45b968
&ival 0x7fff5f45b968

所以我们看到 refValival 具有完全相同的地址(?)和相同的值。它们是同一回事吗?

我也很好奇 int ival = 1024 语句到底发生了什么。我想象这样的事情:

谢谢!

13小时后更新:

再次感谢您的回复。如果可以的话,我想添加一些我认为导致我困惑的上下文:

int ival : 这是一个真正存在的分配 space 在内存的堆栈部分。

int &refVal : 这只是'ival'的别名,没有分配给它space。

'&refVal'等于'&ival',都得到变量'ival'.

的内存地址

嗯,两者的区别是

变量: 变量为我们提供了我们的程序可以操作的命名存储。 C++中的每个变量都有一个特定的类型,它决定了变量内存的大小和布局;该内存中可以存储的值的范围;以及可应用于变量的操作集。

参考: 引用变量是别名,即已存在变量的另一个名称。一旦用变量初始化引用,变量名或引用名都可以用来引用变量。

它基于https://www.tutorialspoint.com/cplusplus/

好吧,如果你还不明白,看看这段代码

 //Pointer
int *p0 ,*p1;
int firstv = 10, secondv = 20;
p0 = &firstv;
p1 = &secondv;
*p0 = 30; // first = 30
*p1 = *p0; // second = 30
std::cout << firstv << std::endl;
std::cout << secondv << std::endl;
p0 = p1; // p0 is pointing at secondv
*p0 = 50; // secondv is now = to 50
std::cout << firstv << std::endl;
std::cout << secondv << std::endl;

简而言之,reference 是一个如上所述的别名,它所做的只是引用变量,一旦它引用该变量,它就像 A = &B 一样,它能做的基本上只是,当您更改变量 A 时,变量 B 也会更改,因为它指的是该变量,正如您在有关 p0 的示例中看到的那样,它指的是 firstv 并且当我们更改 *p0 = 30(p0 指向的值is = to 30) 在第 6 行中,firstv 将等于 30

而变量只是一个存储

总结: 变量只是一个存储 reference 是您用来引用变量的地址

在你的代码中,你输入了 int &refVal = ival 当然它会有相同的地址,因为 &refVal 指的是你变量的地址,因此它们的地址将是相同的

在内部,引用只是一个指针,主要区别在于您不需要使用特定于指针的语法,而且它永远不会是 NULL

它主要用于将参数传递给函数,因为将对象作为参数传递给函数而不复制它的唯一其他方法是使用指针,然后您必须在任何地方使用指针语法。作为引用传递可以使您的代码更加清晰和一致。

引用永远不会单独存在,它总是引用一个存在的变量。

So we see refVal and ival have exactly the same address (?), and the same value. Are they just the same thing?

不,ival 是一个变量:在这种情况下它有自己分配的堆栈内存。 refVal 只是一个 绑定 的名称,您可以将其传递给函数,而无需将 ival 的整个内存复制到函数中的局部变量(重要,因为变量可能比 int)

大得多
int func1(int arg)
int func2(int& arg);

int var = 0;
int& varRef = var;

func1(var); // Entire memory of var is copied into the param named arg.
func2(varRef) // Just the address of 'var' is copied.

引用不能反弹,对变量引用的任何赋值都只是对引用变量的赋值。

varRef = 1; // 'var' itself now has the value of '1'. 

a literal object of type int is created in memory with value 1024

不完全是,这不是 python。

a variable, ival is bind to this object. Is ival a reference to that literal object?

不,没有绑定在这里执行。只是定期分配。 iVal是一个int类型的变量。

I imagine ival will occupy some memory block too, is this correct?

正确,它有大小为 int 的堆栈分配块。

is refVal bind to iVal, or is refVal bind to the literal object (1024) that ival is also bind to?

同样,由于这里没有第三个 "literal" 对象,只有代表 int 内存块的 iVal 和 refVal 绑定到 iVal.

总的来说,参考is a variable。然而,引用 不是 一个对象。引用是引用现有对象的实体。

虽然在许多情况下(但不一定总是)编译器会使用实现指针的相同机制(即传递地址)来实现引用,但在语言级别,指针和引用是完全不同的东西。它们本质上都表达了一种间接性。但是,指针是它自己的对象,有自己的地址,需要显式取消引用它并且可以更改它的值。引用不是对象本身(例如,它没有地址或大小),它是引用现有对象的实体。

声明

int ival = 1024;

int 类型对象的声明和定义,它被初始化为值 1024。所以是的,一个 int 对象被创建并且名称 ival介绍。从那时起,ival 是一个 id-expression,表示特定的 int 对象。

声明

int &refVal = ival;

是引用表达式 ival 指定的 int 对象的引用的声明和定义。从那时起,名称 refVal 是表示该对象的 id-expression。所以是的,名称 refValival 都指定 相同的 int 对象。

注意,虽然ivalrefVal都是变量,但是上面两个声明语句创建的对象只有一个,就是声明定义的int对象介绍ival.

一般来说,名称ival本身只需要存储在编译器和链接器在编译期间使用的内部数据结构(符号表)中。 ival 只是您在代码中用来标识对象的名称。编译后的机器代码将简单地访问标识符相应标识的任何对象(例如,通过其地址)。在程序运行期间无需显式表示名称(动态链接和调试信息除外)。您很可能在编译(发布)二进制文件中的任何地方都找不到字符串 "ival"。