c++ 引用
引用的概念
应用不是重新去定义一个变量,而是给变量取别名。
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空
间,它和它引用的变量共用同一块内存空间
比如:
int a = 10;
int& b = a; //这就是一个引用操作。
// 1. 它的意思并不是把a的值给b
// 2. 也不是把a的地址给b;
// 3. 它的意思是给a取另外一个名字:b
就像:你叫 张伟 :int 张伟
给你取个外号叫张益达: int& 张益达 = 张伟
注意
& 这个符号,只有在int(类型) + & + b(变量)
只有在类型和变量中间才会表示引用的意思。
在其他地方可能有其他的意思:比如:
cout << &b << endl;
//这个时候 & 就是取地址的意思
由于引用共用一个内存空间:所以&a
和&b
是一样的地址。
并且:你对b++, a 也会++; 你对a++,b 也会++; 因为它们的内存空间是同一块的
就像:叫 张伟 是在叫你,叫 张益达 也是在叫你;
#include<iostream>using namespace std;void swap(int& a, int& b) //有了引用,写交换函数就不用指针了
{int tmp = a;a = b;b = tmp;
}int main()
{int a = 10;int b = 12;swap(a, b);cout << a << endl;cout << b << endl;return 0;
}
注意:引用类型必须和引用实体是同种类型的 , 就是你给int a 取别名为 b , 那 b 也该是 int 类型的。int & b = a;
引用的特性
-
引用在定义时必须初始化, 即:int& b = a;
-
一个变量可以有多个引用,
即:int& b = a; int& c = a; int& d = a, 可以给a 取别名为b, c, d 。甚至可以给别名取别名:int & b = e, int & c = f;
-
引用一旦引用一个实体,再不能引用其他实体 , 如上:b,c ,d, e, f已经是a的别名了,那么就不能作为其他变量的别名了
引用做返回值
传值返回
//传值返回
int count()
{int n = 0;n++;return n; //传值返回并不是返回的n,因为程序在执行完这个函数后,这个函数的栈帧就会被销毁,n也就被销毁了,
} //所以传值返回是将要返回的那个值拷贝一份放在一个地方,然后返回的拷贝的那个值int main()
{int ret = count();return 0;
}
传引用返回
//传引用返回
int& count()
{int n = 0;n++;return n; //返回的值是n的别名//count 这个函数执行完后,它的函数栈帧也会被销毁,n也会被销毁,n 都被销毁了,n 的别名也没有任何意义了,//这种情况类似于野指针: 指针所指向的内容被销毁了,但你仍然在使用这个指针。
} int main()
{int &ret = count();//所以这里打印的结果可能是1,也可能是随机值。为啥可能是1?因为你的栈帧虽然被销毁了但是那个空间可能还没有被覆盖, cout << ret << endl;cout << ret << endl;return 0;
}
注意
如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用
引用返回,如果已经还给系统了,则必须使用传值返回
常引用
在引用的过程中有以下的特点:
权限不能放大
const int a = 10;
int& b = a; //这种写法就是错的,因为a本来是被 const 限制了的,但是你给它取的别名没有被限制
权限可以平移
const int a = 10;
const int& b= a;
权限可以缩小
int a = 10;
const int& b = a;
其他
int a = 10;
double& b = a; //这样的写法是错的,错误并不是因为类型不同。
//但是 加个const就行了
const double& b = a;
//因为在发生类型转换时会产生一个临时的变量,这里不是把a直接给b,而是把a给一个临时变量,这个临时变量是double类型
// 临时变量是具有常性的,临时变量如果直接给b的话,就相当于权限的放大了
// 所以我们用const限制一下b