我对参考返回/输入类型感到困惑。 我想我最好通过解释我的理解来问我的问题。
当引用作为参数输入函数时,如下所示......
void squareByReference( int & );
int main ()
{
int z = 4;
sequareByReferece( z );
return 0;
}
int squareByReference( int &numberRef )
{
numberRef *= numberRef;
}
我理解为'squareByReference',& numberRef被函数接收为int变量的地址,但'somehow'可以像普通的int变量一样被识别和处理。因此,行'numberRef * = numberRef;可以将numberRef视为普通的int,即使它实际上是一个地址。
我对此很好。我明白了,解释/编码程序没问题。
然而,当归结为引用返回时,它让我感到困惑。
int g_test = 0;
int& getNumberReference()
{
return g_test;
}
int main()
{
int& n = getNumberReference();
n = 10;
std::cout << g_test << std::endl; // prints 10
std::cout << getNumberReference() + 5 << std::endl; // prints 15
return 0;
}
我的困惑是:为什么'n'被定义为引用int变量?!按照我之前的逻辑,getNumberReference()返回一个引用变量,即使它实际上是一个int的地址,它应该“某种程度上”被视为等于普通的int变量。因此,它应该保存在int变量中而不是引用int变量!当涉及到'std :: cout&lt;&lt;这一行时,这种逻辑非常正常。 getNumberReference()+ 5&lt;&lt;的std :: ENDL ;.”它被“某种程度上”视为普通的int变量并打印15。
请你纠正我的理解来解决我关于int&amp; amp;的问题。定义???
答案 0 :(得分:2)
当您谈论引用时,您必须区分语法和语义。引用的语法 - 一旦初始化/绑定到对象 - 几乎与正常变量相同。然而,它们的语义与指针更相似 - 就函数参数和返回类型而言 - 通常以完全相同的方式实现。
功能参数
将引用作为函数参数传递意味着每次访问该变量时,实际上都会访问原始对象,就像传递指针并取消引用它一样。
现在在函数内部,您通常会看到传递值或按引用传递没有区别,因为(在单线程代码中)您是唯一一个无论如何都要更改该变量的内容,因此对您而言无关紧要正在研究实际的对象或副本。一种情况,即不再是这样的情况是参数是否相互混淆:
void foo(int& a, int& b) {
a=1;
std::cout << b << std::endl;
}
int main() {
int p=2;
foo (p,p); //this will print 1 instead of 2;
}
当然它在函数之外总是很重要,因为通过引用传递你改变了函数之外的原始对象,并且只传递了值,你只更改了本地副本。
功能返回值
没有什么能阻止你写作:
int n = getNumberReference();
在这种情况下返回的引用将被视为“普通的int变量”,因此n
最终将成为该对象的副本,您将打印0和5来代替。
但是,您正在做的是创建一个新引用并将其绑定到任何getNumberReference()
返回。如果getNumberReference将返回一个纯int,那么您的程序将遇到未定义的行为,因为您正在引用一个不再存在分号的临时变量。
但是,您的代码返回引用而n
未绑定到返回的引用本身,而是绑定到首先引用引用的对象(如复制指针)。碰巧的是,该对象是一个全局对象,其生命周期超过main
内的任何内容,因此{分号}后可以安全地使用n
。因此,n
和g_value
现在是两个代表内存中同一对象的名称,每当您通过其中一个名称更改该对象时,您可以通过另一个名称观察到该更改。这就是为什么通常不好的做法,如果一个范围内的多个(非常量)标识符别名同一个对象。
总而言之,在大多数情况下,最好将引用视为指针的语法糖而不是正常变量。