所以我在引用和指针上看到很多问题,但是我的困惑是变量和引用之间有什么区别。例如以下代码:
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
因此,我们看到refVal
和ival
具有完全相同的地址(?)和相同的值。他们只是同一件事吗?
我也很奇怪int ival = 1024
语句会发生什么。我想像这样:
int
的文字对象,其值为1024 ival
绑定到该对象。 ival
是对该文字对象的引用吗? ival
也将占用一些内存块,对吗?refVal
绑定到iVal
,还是refVal
绑定到ival
也绑定到的文字对象(1024)?谢谢!
13小时后更新:
再次感谢您的答复。如果可以的话,我想添加一些我认为会引起困惑的上下文:
ival
和refval
只是同一对象的两个名称,为什么我们完全需要概念“引用”? 答案 0 :(得分:3)
int ival
:这是内存堆栈部分中确实存在的已分配空间。
int &refVal
:这只是'ival'的另一个名称,没有分配空间。
'&refVal'
等于'&ival'
,它们都获得变量'ival'
的内存地址。
答案 1 :(得分:2)
在内部,引用只是一个指针,主要区别在于您不需要使用特定于指针的语法,并且绝对不能为NULL
。
对于将参数传递给函数最有用,因为将对象作为参数传递给函数而不复制它的唯一其他方法是使用指针,然后您必须在各处使用指针语法。作为参考传递,可以使您的代码更加清晰和一致。
引用永远不会单独存在,它将始终引用现有变量。
答案 2 :(得分:1)
因此,我们看到refVal和ival具有完全相同的地址(?),并且 相同的值。他们是同一回事吗?
否,ival
是一个变量:在这种情况下,它具有自己分配的堆栈内存。 refVal
只是一个 bound 的名称,您可以将其传递给函数,而无需将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.
引用不能为 rebound ,并且对变量引用的任何赋值仅是对引用变量的赋值。
varRef = 1; // 'var' itself now has the value of '1'.
在内存中创建一个int类型的文字对象,其值为1024
不完全是,这不是python。
一个变量,ival被绑定到该对象。 ival是指那个 文字对象?
不,没有绑定在这里执行。只是定期分配。 iVal是int类型的变量。
我想象ival也将占用一些内存块,对吗?
正确,它已为栈分配的块大小为int
。
是refVal绑定到iVal,还是refVal绑定到文字对象(1024) 那个节日也与之绑定?
同样,因为这里没有第三个“文字”对象,所以仅iVal表示int
内存块,而refVal
绑定到iVal
。
答案 3 :(得分:1)
通常,引用为is a variable。但是,引用不是它自己的对象。引用是引用现有对象的实体。
尽管在许多情况下(但不一定总是)编译器将使用相同的机制(即地址的传递)来实现指针,该机制也实现了引用,但在语言级别,指针和引用是完全相同的不同的东西。它们本质上都表示一个间接的。但是,指针是其自身的对象,具有自己的地址,需要显式地取消引用它,并且可以更改其值。引用不是对象本身(例如,它没有地址或大小),而是引用现有对象的实体。
声明
int ival = 1024;
是类型为int
的对象的声明和定义,该对象已初始化为值1024。因此,是的,创建了一个int
对象,名称为ival
介绍。从那时起,ival
是一个id-expression,表示那个特定的int
对象。
声明
int &refVal = ival;
是引用的声明和定义,引用引用由表达式int
指定的ival
对象。从那时起,名称refVal
是表示该对象的 id-expression 。因此,是的,名称refVal
和ival
都指定相同的 int
对象。
请注意,虽然ival
和refVal
都是变量,但上面的两个声明语句仅创建一个对象,这是引入{的声明所定义的int
对象{1}}。
通常,名称ival
本身仅需要存储在编译期间编译器和链接器使用的内部数据结构(符号表)中。 ival
只是您在代码中用来标识对象的名称。编译后的机器代码将仅访问标识符相应标识的任何对象(例如,通过其地址)。无需在程序的运行过程中显式表示名称(动态链接和调试信息除外)。您很可能在已编译(发行)二进制文件的任何位置都找不到字符串“ ival”。
答案 4 :(得分:0)
两者之间的区别是
变量: 变量为我们提供了程序可以操纵的命名存储。 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;
简而言之,就是上面提到的别名,它的作用是仅引用变量,一旦引用该变量,它将就像A =&B一样,并且基本上可以执行以下操作:更改变量A,变量B也将更改,因为它引用了该变量,正如您在有关p0的示例中所指的是firstv一样,并且当我们更改* p0 = 30时(由p0指向的值是=到30)在第6行中,firstv等于30
变量只是存储空间
摘要: 变量只是一个存储 引用是您用来引用变量的地址
在您的代码中,您将int&refVal = ival放在了正确的位置,因为&refVal引用的是您变量的地址,因此它的地址将相同。