目录
什么是引用?
变量名实质就是一段连续内存空间的别名。那一段连续的内存空间只能取一个别名吗? 显然不是,引用的概念油然而生。在C++中,引用是一个已定义变量的别名。
其语法是:类型 &引用名 = 目标变量名; void test0() { int a = 1; int &ref1 = a; }
在使用引用的过程中,要注意以下几点:
1. &在这里不再是取地址符号,而是引用符号,相当于&有了第二种用法
2. 引用的类型必须和其绑定的变量的类型相同
3. 声明引用的同时,必须对引用进行初始化;否则编译时报错
4. 一旦绑定到某个变量之后,就不会再改变其指向1.引用是一个变量的别名,在定义时必须进行初始化.
2.引用提出来的目的主要是减少指针的使用
3.操作引用和操作实体本身是一样的
引用的本质
C++中的引用本质上是一种被限制的指针。类似于线性表和栈的关系,栈是被限制的线性表,底层实现相同,只不过逻辑上的用法不同而已。
由于引用是被限制的指针,所以引用是占据内存的,占据的大小就是一个指针的大小。有很多的说法,都说引用不会占据存储空间,其只是一个变量的别名,但这种说法并不准确。引用变量会占据存储空间,存放的是一个地址,但是编译器阻止对它本身的任何访问,从一而终总是指向初始的目标单元。在汇编里, 引用的本质就是“间接寻址”。
引用作为函数参数
在没有引用之前,如果我们想通过形参改变实参的值,只有使用指针才能到达目的。但使用指针的过程中,不好操作,很容易犯错。 而引用既然可以作为其他变量的别名而存在,那在很多场合下就可以用引用代替指针,因而也具有更好的可读性和实用性。这就是引用存在的意义。
一个经典的例子就是交换两个变量的值。//用指针作为参数 void swap(int *pa, int *pb) { int temp = *pa; *pa = *pb; *pb = temp; } //引用作为参数 void swap(int &x, int &y) { int temp = x; x = y; y = temp; }
参数传递的方式除了上面的指针传递和引用传递两种外,还有值传递。
采用值传递时,系统会在内存中开辟空间用来存储形参变量,并将实参变量的值拷贝给形参变量,即形参变量只是实参变量的副本而已;如果函数传递的是类对象,系统还会调用类中的拷贝构造函数来构造形参对象,假如对象占据的存储空间比较大,那就很不划算了。这种情况下,强烈建议使用引用作为函数的形参,这样会大大提高函数的时空效率。
当用引用作为函数的参数时,其效果和用指针作为函数参数的效果相当。当调用函数时,函数中的形参就会被当成实参变量或对象的一个别名来使用,也就是说此时函数中对形参的各种操作实际上是对实参本身进行操作,而非简单的将实参变量或对象的值拷贝给形参。
使用指针作为函数的形参虽然达到的效果和使用引用一样,但当调用函数时仍需要为形参指针变量在内存中分配空间,而引用则不需要这样,故在C++中推荐使用引用而非指针作为函数的参数
引用作为函数的返回值
//语法: 类型 &函数名(形参列表) { //函数体 }
当以引用作为函数的返回值时,返回的变量其生命周期一定是要大于函数的生命周期的,即当函数执行完毕时,返回的变量还存在。
int gNumber;//全局变量 int func1() // 当函数返回时,会对temp进行复制 { temp = 100; return temp;//此处会进行复制操作 } int &func2()//当函数返回时,不会对temp进行复制,因为返回的是引用 { temp = 1000; return temp; }
当引用作为函数的返回值时,必须遵守以下规则:
1. 不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
2. 不能在函数内部返回new分配的堆空间变量的引用。如果返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么该引用所在的空间就无法释放,会造成内存泄漏。int &func3() { int number = 1; return number; } int &func4() { int *pInt = new int(1); return *pInt; } void test() { int a = 3, b = 4; int c = a + func4() + b;//内存泄漏 }
引用与指针的区别
1.初始化:引用在定义时必须初始化,指针则没有要求(尽量初始化,防止野指针)
2.引用在初始化引用一个实体后,就不能再引用其它实体,而指针可以在任意时候指向一个同类型实体
3.没有NULL引用,但是有nullptr指针
4.在sizeof中含义不同: 引用结果为引用类型的大小,但指针始终是地址空间,所占字节个数(32位平台占4个字节)
5.引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
6.有多级指针,但没有多级引用
7.访问实体的方式不同,指针需要显式解引用,引用编译器自己处理
8.引用比指针使用起来相对安全
引用总结:
1. 在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不如意的问题。
2. 用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。
3. 引用与指针的区别是,指针通过某个指针变量指向一个变量后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。