什么是返回引用,返回引用的概念及定义?

营销圈公众号引导关注

引用是C++的概念,在C中没有此定义。引用本质上是一个由编译器实现了解引用的指针常量。

引用本质上应该是一个指针常量,它的值初始化为其指向的变量,此后使用时无须解引用即直接表示其指向变量的值。它是一个常量,不能再指向其它变量,但指向的变量当然是一个可以更新的变量。

引用也可以理解为变量的别名,变量直接使用变量对应的内存单元中的值,而引用是指向变量对应的内存单元。与指针不同,指针需要创建一个指针变量(局部变量),用于保存指向的变量的内存单元地址。而引用与引用指向的变量的内存地址是同一的。

引用作为变量的别名,一些人认为其本身是不占用内存空间(指针占用一个字长的内存空间保存一个地址值),但到底占不占用内存空间来保存一个地址值呢?其实是占用一个字长的内存的,详细分析请见:

C++|引用占用内存空间吗?可改变吗?本质上是一个指针常量吗?

使用引用指向的变量的值时也与使用指针时不同,指针需解引用,引用不需要,可以如同变量一样使用。

复制庞大而复杂的值有昂贵的开销。为了避免传递副本的开销,可将函数形参指定为引用类型。对引用形参的任何修改会直接影响实参本身。应将不需要修改相应实参的引用形参定义为 const 引用。

引用有指针一样的威力,但语法要简单一些。

如有一个int的someInt变量,就可以定义一个引用:

int someInt;
int &rSomeRef = someInt;

rSomeRef与someInt的地址是同一的。

在C++中&现出在声明或等式的左边时,是引用,出现在等式的右边时,是取址。

引用比指针更容易使用和理解,引用的间接关系被隐藏,无须不断解引用。

但引用不能为空,也不能重新赋值。指针提供了更大的灵活性,但使用起来更难。

引用的定义:给一个变量取一个别名,例:
int i;
int &j=i;
j是i的别名,i与j是同一个内存单元。
引用实际上是一种隐式指针。每次使用引用变量时,可以不用书写间接引用运算符“*”,因而引用简化了程序。

C++引入引用的主要目的是将引用作为函数的参数。

定义引用时必须立即对它初始化,不能定义完成后再赋值。如:

int i;
int &j; //错误
j=i;

为引用提供的初始值可以是一个变量或另一个引用。如:

int i=5;
int &j1=i;
int &j2=j1;

引用主要用于函数参数,相对于指针和传值,引用变量不需要占用内存空间;相对于传值,不需要因为赋值而浪费时间(指针参数也有此优势);相对于指针,函数体内不需要使用解引用*符号,显得更简洁。

引用是与变量的固定关联,而指针却可以修改为指向其它空间。引用这种语法机制的定义主要是为了突破函数参数对数据的保护,我们知道,函数参数默认传递的方式是值传递,让引用做参数时传递的是地址值。

1 引用做函数参数

引用是对象的另一个名字,在实际程序中,引用主要用作函数的形式参数来使用。

按值传递时,将变量的备份而不是变量本身传递给函数,这让函数无法修改原始值。为了避免按值传递,一种方式是使用指针,这将传递原始变量的地址;另一种方式是使用引用,这将传递原始变量的别名。

按引用传递可以避免创建备份。

处理大量数据时,按引用传递比按值传递要好,可以更节省内存,因为不需要复制参数复本。

引用如果是参数传递,则引用传递的是一个变量的内存地址,而不是值。

在C++中,值传递是指将要传递的值作为一个副本传递。值传递过程中,被调函数的形参作为被调函数的局部变量处理,在内存的堆栈中开辟空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形参的任何操作都是作为局部变量进行,不会更改主调函数的实参变量的值。

引用传递传递的是引用对象的内存地址。在地址传递过程中,被调函数的形参也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。所以,被调函数对形参做的任何操作都会影响主调函数中的实参变量。

传值方式适合一般数值传送,并且不改变原数据,但要消耗内存空间。

传指针方式适合传递数组、指针,由于传递的是地址,所以直接操作会改变原数据。

引用方式和指针比较类似,是相对比较新的一种方式。一般情况下能用传址的就能用引用,而且使用引用更方便一点(无须解引用即可引用指向的值)。

引用传递是地址传递的另一种更简单明了的实现方法。

指针作为函数参数:

void swap(int *m, int *n)
{ 
 int temp;
 temp=*m;
 *m=*n; *n=temp;
}

调用:swap(&x, &y);

引用作为函数参数:

void swap(int &m, int &n)
{
 int temp;
 temp=m;
 m=n; n=temp;
}

调用:swap( x, y);

注意:实参必须是变量,而不能是一个表达式。

在C++中,函数参数一般都采用引用传递。

利用引用传递的好处是减少函数调用时的开销。

如果在函数内不许改变参数的值,则参数用const限定。

对非const的参数,实际参数不能是常量或临时量。

2 引用作为函数返回值

函数的返回值可以是引用,此时的函数调用可以用做左值。

通常,对于数组下标的重载会返回一个引用,以便能用左值。

int a[] = {1, 3, 5, 7, 9};
int &index(int); //声明返回引用的函数
void main()
{
 index(2) = 25; //将a[2]重新赋值为25
 cout << index(2);
}
int &index(int j)
{return a[j];} //函数是a[j]的一个引用

3 引用的本质是一个指针常量

引用本质上是一个由编译器实现了自动解引用的指针常量。

引用&也可以理解为一个变量的别名,例如:

int& b=a;//b声明为a的引用

b和a拥有相同的内存地址,可以通过改变b的值来改变a包含的值。

指针常量表示存储在指针中的地址不能修改;像这样的指针只能指向初始化时指定的地址,但是,地址中的内容不是常量,可以修改;(和指向常量的指针不同,指向常量的指针称为常量指针,表示指向的内容是常量,不能够修改其指向的内容)。

至于引用和指针常量的区别:

int& b=a;
int* const p=&a;

b是a的引用,他们拥有相同的内存地址,指针p存储的是变量a的地址,指针p自己拥有另一个内存地址,可以通过间接运算符来解除指针的引用:

int c=*p;

而引用却是由编译器实现了自动的解引用:

int c = b;

4 C++引用和指针的区别

指针可以申请动态内存并实现动态数组,函数指针参数传址可以更新函数外部的值,同时用指针传址不需要再为参数开辟内存空间,当涉及到大批量数据时,这样的设计更有效率。其它语言也通过其它的方式(如引用)来达成类似的操作。

在C、C++中,就引入了指针的概念来映射内存中的地址并表示这个地址的线性关系。

使用引用清晰、简便,然而,引用也有其局限性。引用不能重新赋值,如果需要依次指向不同的对象,就必须使用指针。引用不能为NULL,因此如果要指向的对象可能为NULL,就必须使用指针,而不能使用引用。如果需要从堆中分配动态内存,也必须使用指针。

4.1 引用必须指向一个对象,C++要求引用必须初始化,并且没有NULL引用这种概念。

4.2 指针可以被重定向指向不同的对象,引用只能指向它初始化指向的对象。

引用只能在定义时被初始化一次,之后不可变,指针可变。给引用赋值并不是改变它和原始对象的绑定关系,而是其引用的内存单元的值的更新。

int i, k;
int &j=i;
j=&k;//错误
j=33; //更新i的值

4.3 引用不能为空,指针可以为空。基本上,当你可能会指向空(或什么都不指向)或可能会在不同时间指向不同对象的时候,使用指针!反之,则使用引用。不存在NULL引用,引用必须与合法的存储单元关联;而指针则可以是NULL。

4.4 指针是一个实体,而引用仅是个别名。

4.5 引用使用时无需解引用(*),指针需要解引用。

4.6 引用没有 const,指针有const。

4.7 使用sizeof衡量大小的区别

“sizeof(引用)”得到的是所指向的变量(对象)的大小,而“sizeof(指针)”得到的是指针本身(所指向的变量或对象的地址)的大小,就是一个字长。

4.8 自增(++)运算意义不一样.

引用的自增是值的自增,而指针的自增是指针的偏移。

总的来说,引用既具有指针的效率,又具有变量使用的方便性和直观性。

另外,引用比较安全,当然也有其局限性,如上所述,指针也有其单独适用的场合。

-End-

好了,这篇文章的内容营销圈就和大家分享到这里,如果大家对网络推广引流和网络创业项目感兴趣,可以添加微信:Sum8338 备注:营销圈引流学习,我拉你进直播课程学习群,每周135晚上都是有实战的推广引流技术和网络创业项目课程分享,当然是免费学!

版权声明:本站部分文章来源互联网用户自发投稿,主要目的在于分享信息,版权归原作者所有,不承担相关法律责任。如有侵权请联系我们反馈邮箱yingxiaoo@foxmail.com,我们将在7个工作日内进行处理,如若转载,请注明本文地址:https://www.yingxiaoo.com/133335.html