目录
1-引用的基本使用
2-引用的注意事项
3-引用作为函数参数
4-引用作函数返回值
5-引用的本质
6-常量引用
1-引用的基本使用
引用的本质就是给一个变量起个小名。
语法:数据类型 &别名 = 原名
比如说int a = 10,这样就相当于申请了一块4个字节大小的内存,存放了10这个数据,而且可以用a这个变量去操作这块内存空间。
现在有个疑问,能不能再取个变量名去操作这块内存呢?以前是用指针来实现这一操作,比如int*p=&a,但是懒狗会说,每次还要整个*解引用,很烦,我就想直接取个小名,像typedef那样。
C++就提供了引用技术来实现这个功能,int &b = a,那么这时b的地址也指向a的地址处,b也可以像a一样的去操作那一块内存。
void test01()
{
int a = 10;
int& b = a;
b = 20;
cout << a << endl;
}
输出结果是20,证明了可以通过直接访问b,来找到原本属于a的那一块内存空间!
注:引用自身也是需要内存空间的!在5小节本质中会提到。
2-引用的注意事项
⭐引用是必须初始化的!
void test02()
{
int a = 10;
int& b = a;
int& c;
}
这里的c就是一个非法的引用变量,引用自身不管理内存空间!它只是另外一个变量的小名罢了,所以必须要初始化,如果不给的话编译器不知道怎么对它进行操作。
⭐引用在初始化后不允许改变!
void test02()
{
int a = 10;
int& b = a;
int c = 20;
b = c;
}
本来b是a的别名,也可以访问a的那一块内存空间,假设现在又有一个变量c,c管理另外一块内存空间,现在想把b变成c的小名是不可以的!
3-引用作为函数参数
作用:函数传参时,可以利用引用技术让形参来修饰实参
优点:可以简化指针修改实参
#includeusing namespace std; //值传递 void mySwap01(int a,int b) { int temp = a; a = b; b = temp; } void test01() { int a1 = 10; int b1 = 20; cout<<"交换前a1 = "<
①值传递的话,是无法改变实参的值的,传入的是一份拷贝的数据,相当于在梦里进行交换,实际不会改变!
②地址传递,形参是会修饰实参的,即形参在其中的变化会实际投射到实参身上。
③引用传递参数,形参也会修饰实参,并且可以省略掉解引用操作,可以在某种程度上视作这里的形参就变成了实参的别名,所以在函数内部对形参的操作,也就是在操作实参!
引用就是在简化指针操作,理解起来会更加的简单。
4-引用作函数返回值
引用是可以作为函数的返回值存在的
⭐不要去返回一个局部变量的引用
#includeusing namespace std; //值传递 int& test01() { int a = 10;//栈区存放局部变量 return a; } int main() { int& ref = test01(); cout << ref << endl; cout< 这里的test01返回值类型是int&,代表的意义是要将某个东西以引用的方式带出来,而a是一个局部变量,正常来说直接返回10就可以,如果是引用的方式来返回,ref拿到的就是这个a,而不是10这个值了。
第一次输出ref,能够正常输出10这个值,第二次就变成乱码了,这是因为编译器做了一个保留操作,但其实这块内存在被函数结束后已经被释放了,我们是没有权力去操纵他的!
所以不要用引用的方式将局部变量带出它的生命周期!
int& test02() { static int a = 10;//静态变量是存放在全局区的,全局区变量在程序结束后由系统释放 return a; }修改方式也很简单,加上static关键字让a变成一个全局变量即可!
⭐函数的调用作为左值
#includeusing namespace std; //值传递 int& test02() { static int a = 10;//静态变量是存放在全局区的,全局区变量在程序结束后由系统释放 return a; } int main() { int& ref = test02(); cout <<"ref = " << ref << endl; cout <<"ref = " << ref << endl; test02() = 1000; cout << "ref = " << ref << endl; cout << "ref = " << ref << endl; system("pause"); return 0; } test02() = 1000,在这里,一个返回值类型为引用的函数可以当作一个左值来处理数据,这是因为test02()返回值类型是int&,返回出来的是一个变量,那么也就是相当于a = 1000,改变了那一块内存的值,再区打印ref,那么结果也会跟着改变。
5-引用的本质
引用的本质在C++内部实际上是一个指针常量。
注:指针常量是指针指向的地址无法修改,而地址中的值可以改变!
#includeusing namespace std; void func(int& ref)//接收到a,发现是引用传递,转换为int * const ref = &a; { ref = 100;//ref是引用,自动转换为*ref = 100 } int main() { int a = 10; int& ref = a;//转换为int* const ref = &a; ref = 20;//自动转换,*ref = 20; cout << "a = " << a << endl; cout << "ref = " << ref << endl; func(a);//传入一个int类型的变量 system("pause"); return 0; } 这就很好的解释了为什么引用不能够再修改,因为它的指向是规定死了的,是无法改变的!
可以认为,引用名 = *指针名,只是C++里省略了这个解引用操作,使得很多东西变得简单。
在C++中,推荐使用引用技术,因为&实在是太方便了。
6-常量引用
常量引用主要是用来修饰形参的,防止误操作。
即在函数的形参列表当中,在形参前加上const进行修饰,防止形参改变实参。
int a = 10; int& ref = 10;首先要明确,这样的语句是有问题的,引用的对象必须是一块合法的内存空间,而不能直接引用一个常量!
const int& ref = 10;而这样的代码却是合法的,其实const申请了一块临时空间,相当于先int temp = 10,
再const int &ref=temp,不过要记得,现在是不允许修改的了。
#include#include using namespace std; void showValue(const int& val) { val = 1000; cout << "val = " << val << endl; } int main() { int a = 100; showValue(a); return 0; } 在形参前加上const,避免在函数内部对这个参数进行修改,一旦改变值就会报错,这就是一个保护作用,防止的就是有时候改变了实参的值!形参导致实参值改变从而出错。



