引言:
对于某些初学者来看,往往会出现如下错误:
可以看到,在函数 fun1 中,我们明明把变量 a 赋值了 10,却在最后输出的时候仍为初始值 0。这是为什么呢?
这是由于函数fun1在调用时,所用到的参数a其实是主函数a的一个拷贝,这俩位于不同的地址。
正是由于函数的形参只是所传实参的一份拷贝,相当于另外开了一个空间存储所传的数据。我们知道所有数据是存储在一个地址空间里面的,当我们在函数中改变形参时,由于所存储的地址不同,这样使得函数只能改变处于形参地址处的数据,而无法改变实参地址处的数据。
这样就会导致出现了如上的问题。那我们应该如何解决这个问题呢?这里我会提到两种方法,一种是利用指针,另一种则是本博文重点,C++中的引用。
指针法我们就简单介绍一下,主要是在函数的传参时,所传参数并不是实参本身,而是实参的地址,当我们直接通过实参的地址,就可以在函数中修改实参的值了。
引用的用法:
首先了解一下引用的概念:引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间, 它和它引⽤的变量共⽤同⼀块内存空间。就比如说,你有一个好兄弟叫张三,而你经常叫他三儿,这个三儿就是他的别名,也指代的是你的兄弟,他们是同一个人。
用法:类型& 引⽤别名 = 引⽤对象;
可以看到,当我们给别名b赋值时,a的值也跟着改变,并且别名b的存储空间和本名a的存储空间一样。
下面是解决上门函数问题的图示:
引用的特性:
一.引⽤在定义时必须初始化
上面提到,引用是给已有的变量去一个别名,也就是说当引用在定义时必须初始化。就好比说你不可能给一个不存在的人取外号。
二.一个变量可以有多个引用
可以看到,a,b都是x的别名,随便改变其一都可以改变x的值。
另外,也可以给引用取别名:
可以看到,无论是别名的别名,还是别名与本名,都指向同一块空间,都可以修改本名的值。
三.引用⼀旦引用⼀个实体,再不能引用其他实体
根据上面的介绍,我们都清楚引用和实体处于同一空间,根据如图执行结果我们可以看出,a与x的地址一样,说明了 a 还是 x 的别名, y 的地址与 x 和 a 都不同,这些说明了 a=y 这一操作是把y的值赋给a,从而使x=y=1。这也说明了引用⼀旦引用⼀个实体,再不能引用其他实体。
引用的优点:
1.引⽤在实践中主要是于引⽤传参和引⽤做返回值中减少拷⻉提⾼效率和改变引⽤对象时同时改变被引⽤对象(实参)。
引言提到函数的形参实际上是实参的一个拷贝,但当我们使用引用时,由于指向了和实参同一块空间,因而提高了拷贝的效率,同时也可以达到改变实参的目的。
2.引⽤传参跟指针传参功能是类似的,引⽤传参相对更⽅便⼀些。
另外:
引用做返回值的情况比较复杂,该项会在类和对象中做以介绍。下面仅提供一个使用对比样例。
可以看到,当我们想要把一个数组的首元素改为1时,不使用引用返回需要在函数内部进行操作,而使用引用返回则可以直接在主函数内部进行随意更改。
希望本文能给你带来帮助,点赞支持一下吧。THANKS;
下面是本文测试代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//void fun1(int& a)
//{
// a = 10;
// cout << &a << endl;
//}
//
//int main() {
// int a = 0;
// fun1(a);
// cout << a << endl;
// cout << &a << endl;
//
// return 0;
//}
//int main() {
// //int a = 0;//创建一个初始值为0的变量a
// //int& b = a;//给a取了一个别名b
// //b = 20;//给b赋值20
// //cout << "a=" << a << " b=" << b << endl;
// //cout << "a的地址=" << &a << endl << "b的地址为=" << &b;
// //int x = 0;
// //int& c;
// /*int x = 0;
// int& a = x;
// int& b = x;
// a = 10;
// cout << x << endl;
// b = 20;
// cout << x << endl;*/
// //int x = 0;
// //int& a = x;
// //int& b = a;
// //b = 20;
// //cout << x << endl;
// //cout << "&x=" << &x << endl;
// //cout << "&a=" << &a << endl;
// //cout << "&b=" << &b << endl;
// //int x = 0;
// //int y = 1;
// //int& a = x;//给x取一个别名a
// //a = y;//该操作是给y取别名还是把y的值赋给a?
// //cout << "x=" << x << endl;
// //cout << "y=" << y << endl;
// //cout << "&a=" << &a << endl;
// //cout << "&x=" << &x << endl;
// //cout << "&y=" << &y << endl;
// return 0;
//}
int fun1(int* a)
{//不使用引用返回
a[0] = 1;
return 0;
}
int& fun2(int* a)
{ //使用引用返回
return a[0];
}
int main()
{ int a[10] = { 0 };
int b[10] = { 0 };
fun1(a);
cout << a[0] << endl;
fun2(b) = 1;
cout << b[0] << endl;
return 0;
}