C++ 函数 Return/Input 引用类型
C++ Function Return/Input Reference Type
我对参考 return/input 类型太困惑了。
我想我最好通过解释我的理解来提出我的问题。
当如下所示将引用作为参数输入函数时...
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,即使它实际上是一个地址。
我同意这个。我明白了,没问题 interpreting/coding 个程序。
然而,当涉及到参考return时,让我很困惑。
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() return 是一个引用变量,即使它实际上是一个 int 的地址,它也应该 'somehow' 被视为等于普通的 int 变量。因此,它应该保存在int变量中而不是引用int变量!当涉及 'std::cout << getNumberReference() + 5 << std::endl;.' 行时,此逻辑工作得很好。它被 'somehow' 视为普通的 int 变量并打印 15.
能否请您纠正我的理解以解决我关于 int& 定义的问题???
当你在谈论引用时,你必须区分语法和语义。引用的语法 - 一旦它们是 initialized/bound 一个对象 - 几乎与普通变量相同。然而,它们的语义更类似于指针,并且 - 就函数参数和 return 类型而言 - 通常以完全相同的方式实现。
函数参数
将引用作为函数参数传递意味着每次访问该变量时,实际上访问的是原始对象,这与传递指针并取消引用它的方式相同。
现在在一个函数中,你通常会发现按值传递或按引用传递之间没有区别,因为(在单线程代码中)你是唯一一个改变该变量内容的人,所以你是否正在处理实际对象或副本。一种情况不再适用,如果参数彼此互为别名:
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;
}
当然,它在函数外部总是很重要,因为通过引用传递,您在函数外部更改了原始对象,而对于值传递,您只更改了本地副本。
函数return值
没有什么能阻止你写作:
int n = getNumberReference();
在这种情况下 returned 引用将被视为 "normal int variable",因此 n
最终将成为副本那个对象,你会打印 0 和 5。
但是,您正在做的是创建一个新引用并将其绑定到任何 getNumberReference()
returns。如果 getNumberReference return 是一个普通的 int,您的程序将 运行 变成未定义的行为,因为您引用的是一个临时变量,该变量在分号之后不再存在。
但是,您的代码是 returning 引用,并且 n
未绑定到 returned 引用本身,而是绑定到首先引用引用的对象(如复制指针).碰巧,该对象是一个全局对象,其生命周期超过 main
内的任何对象,因此可以在分号后安全地使用 n
。结果,n
和 g_value
现在是代表内存中同一个对象的两个名称,每当您通过其中一个名称更改该对象时,您可以通过另一个名称观察到该更改。这就是为什么如果一个范围内的多个(非常量)标识符给同一个对象起别名,这通常是一种不好的做法。
综上所述,在大多数情况下,最好将引用视为指针而不是普通变量的语法糖。
我对参考 return/input 类型太困惑了。 我想我最好通过解释我的理解来提出我的问题。
当如下所示将引用作为参数输入函数时...
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,即使它实际上是一个地址。
我同意这个。我明白了,没问题 interpreting/coding 个程序。
然而,当涉及到参考return时,让我很困惑。
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() return 是一个引用变量,即使它实际上是一个 int 的地址,它也应该 'somehow' 被视为等于普通的 int 变量。因此,它应该保存在int变量中而不是引用int变量!当涉及 'std::cout << getNumberReference() + 5 << std::endl;.' 行时,此逻辑工作得很好。它被 'somehow' 视为普通的 int 变量并打印 15.
能否请您纠正我的理解以解决我关于 int& 定义的问题???
当你在谈论引用时,你必须区分语法和语义。引用的语法 - 一旦它们是 initialized/bound 一个对象 - 几乎与普通变量相同。然而,它们的语义更类似于指针,并且 - 就函数参数和 return 类型而言 - 通常以完全相同的方式实现。
函数参数
将引用作为函数参数传递意味着每次访问该变量时,实际上访问的是原始对象,这与传递指针并取消引用它的方式相同。
现在在一个函数中,你通常会发现按值传递或按引用传递之间没有区别,因为(在单线程代码中)你是唯一一个改变该变量内容的人,所以你是否正在处理实际对象或副本。一种情况不再适用,如果参数彼此互为别名:
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;
}
当然,它在函数外部总是很重要,因为通过引用传递,您在函数外部更改了原始对象,而对于值传递,您只更改了本地副本。
函数return值
没有什么能阻止你写作:
int n = getNumberReference();
在这种情况下 returned 引用将被视为 "normal int variable",因此 n
最终将成为副本那个对象,你会打印 0 和 5。
但是,您正在做的是创建一个新引用并将其绑定到任何 getNumberReference()
returns。如果 getNumberReference return 是一个普通的 int,您的程序将 运行 变成未定义的行为,因为您引用的是一个临时变量,该变量在分号之后不再存在。
但是,您的代码是 returning 引用,并且 n
未绑定到 returned 引用本身,而是绑定到首先引用引用的对象(如复制指针).碰巧,该对象是一个全局对象,其生命周期超过 main
内的任何对象,因此可以在分号后安全地使用 n
。结果,n
和 g_value
现在是代表内存中同一个对象的两个名称,每当您通过其中一个名称更改该对象时,您可以通过另一个名称观察到该更改。这就是为什么如果一个范围内的多个(非常量)标识符给同一个对象起别名,这通常是一种不好的做法。
综上所述,在大多数情况下,最好将引用视为指针而不是普通变量的语法糖。