一、概念
引用不是重新定义一个变量,而是给已存在变量取了一个别名,就像人的小名一样,编译器不会为引用变量开辟内存空间,它和它所引用的变量共用同一块内存,使用时用类型(和引用实体是同种类型的)& 引用变量名(对象名)=引用实体
void ReferenceTest()
{
int a = 1;
int &ra = a;
cout << a << endl;
cout << ra << endl;
cout << &a << endl;
cout << &ra << endl;
}
通过查看它们的值与地址我们可以检验上面的结论
二、特性
(1)引用在定义时必须初始化
(2)一个变量可以有多个引用
(3)引用一旦引用一个实体,再不能引用其他实体
(4)引用的生命周期比实体长
三、常引用
void ReferenceTest()
{
// 1
const int a = 1;
const int &ra = a;
// 2
const int &b = 10;
// 3
double d = 1.1;
const int &rd = d;
}
对于下面这个函数,想一下最后会输出什么呢?
void ReferenceTest()
{
double d = 1.1;
const int &rd = d;
d = 2.2;
cout << d << endl;
cout << rd << endl;
}
看到这个结果,可有人感到神奇呢,rd 怎么还是1,当了解到原理之后,它的面纱将会被揭开,原来 rd 引用的并不是 d 的空间,编译器会创建一个临时空间,把 1 存储进去,rd 引用的是这个临时空间,为什么要加 const 呢,这是因为它引用的是一个具有常属性的临时变量
四、使用场景
1. 做参数
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
2. 做返回值
int& TestRefReturn(int& a)
{
a += 10;
return a;
}
猜一下下面这个函数输出的是多少呢?
void ReferenceTest()
{
int a = 1;
int b = 2;
int &c = Add(a, b);
Add(2, 3);
cout << c << endl;
}
函数返回时,离开函数作用域后,其栈上空间已经还给系统,因此不能用栈上的空间作为引用类型返回,如果以引用类型返回,返回值的生命周期必须不受函数的限制,所以它的值为5
五、引用和指针的区别
|
| 引用 | 指针 |
不同 | 初始化 | 引用在定义时必须初始化, 引用一个实体后,就不能再引用其他实体 | 指针没有要求,可以在任何时候指向任何一个同类型实体 |
NULL | 没有NULL引用 | 有NULL指针 | |
sizeof | 引用类型的大小 | 地址空间所占字节个数 | |
自加 | 引用的实体增加1 | 指针向后偏移一个类型的大小 | |
访问实体 | 引用编译器自己处理 | 指针需要显式解引用 | |
安全 | 引用比指针使用起来相对更安全 | ||
相同 | 都是地址的概念,指针指向一块内存,它的内容是所指内存的地址,引用是某块内存的别名;引用和指针在作为传参以及返回值类型上效率几乎相同 |