1. 引用的意义
(1)引用作为变量别名而存在,因此在一些场合可以代替指针
(2)引用相对于指针来说,具有更好的可读性和实用性

2. 特殊的引用:const引用
(1)在C++中可以声明const引用
(2)const Type& name = var;
(3)const引用让变量拥有只读属性

(4)当使用常量对const引用进行初始化时,C++编译器会为这个常量值分配空间,并将引用名作为这段空间的别名。但这样用常量对const引用初始化将生成的是一个只读变量。
【实例分析】引用的特殊意义 5-1.cpp
#include <stdio.h>
void Example()
{
printf("Example:\n");
int a = 4;
const int& b = a;//变量a的别名,const让变量b具有只读属性
int* p = (int*)&b; //&b就是变量a的地址
//b = 5;//非法,因为用const修饰的引用,其代表的变量是只读的
*p = 5; //合法,修改变量a的值
printf("a = %d\n", a); //5;
printf("b = %d\n", b); //5
}
void Demo()
{
printf("Demo:\n");
//const引用
const int& c = 1; //引用本应是变量的别名。一般,常量是不分配内存的。当编译器看
//该行时,会为常量1分配内存,并让b作为这段空间的别名。
int* p = (int*)&c;
//c = 5;//非法,因为const修饰,c是只读的
*p = 5;//合法,通过指针访问内存
printf("c = %d\n", c); //5
printf("\n", c); //5
//const修饰变量:注意与const引用的区别
const int a = 1;
p = (int*)&a; //遇到&a才为常量分配内存
//a = 5;//非法,因为const修饰,a是只读的
*p = 5;//合法,通过指针访问内存
printf("a = %d\n", a); //1,编译器看到a直接从符号表读其值(1)
printf("*p = %d\n",*p); //5
}
int main()
{
Example();
printf("\n");
Demo();
return 0;
}
运行结果:
3. 引用的本质
(1)引用在C++中的内部实现是一个指针常量,因此引用所占用的空间大小与指针相同。
(2)从使用的角度,引用只是一个别名,C++为了实用性而隐藏了引用的存储空间这一细节。
①在编译过程中,编译器看到int& a的声明就会转换为int* const a;
②看到使用引用时,会转换为*a,如此隐藏了使用指针的事实。
【编程实验】引用的思考 5-2.cpp
#include <stdio.h>
struct TRef
{
char& r; //引用的本质是指针常量,因此会分配4字节的空间,相当于char* const r;
};
int main()
{
char c = 'c';
char& rc = c;
TRef ref = {c};
printf("sizeof(char&) = %d\n",sizeof(char&));//1,char型变量别名,大小为1
printf("sizeof(rc) = %d\n",sizeof(rc)); //1,变量c的别名,大小为1
printf("sizeof(TRef) = %d\n",sizeof(TRef)); //结构体内有个引用,本质为指针,占4字节
printf("sizeof(ref.r)= %d\n",sizeof(ref.r)); //1,char型变量的别名,大小为1
return 0;
}
运行结果:
【编程实验】引用的存储空间 5-3.cpp
#include <stdio.h>
struct TRef
{
char* before; //4字节
char& ref;//4字节,本质是指针常量,会分配4字节的空间,相当于char* const ref;
char* after;//4字节
};
int main()
{
char a = 'a';
char& b = a;
char c ='c';
TRef r = {&a, b, &c};
printf("sizeof(r) = %d\n", sizeof(r)); //12
printf("sizeof(r.before) = %d\n", sizeof(r.before)); //4
printf("sizeof(r.after) = %d\n", sizeof(r.after)); //4
printf("&r.before = %p\n", &r.before);
printf("&r.after = %p\n", &r.after); //after和before相差8个字节,中间隔了个b引用所占用的空间
return 0;
}
运行结果:
4. 引用的意义:C++中的引用旨在大多数的情况下代替指针
(1)功能性:引用在大多数情况下代替指针,可以满足多数需要使用指针的场合
(2)安全性:可以避开由于指针操作不当而带来的内存错误
(3)操作性:简单易用,又不失功能强大
【实例分析】函数返回引用 5-4.cpp
#include <stdio.h>
int& demo()
{
int d = 0;
printf("demo: d = %d\n", d); //输出0
return d;//返回局部变量的引用,危险
}
int& func()
{
static int s = 0;
printf("func: s = %d\n", s);//输出0
return s; //合法,返回的是静态局部变量(位于全局存储区中的)
}
int main()
{
int& rd = demo();
int& rs = func();
printf("\n");
printf("main: rd = %d\n", rd);//垃圾数值
printf("main: rs = %d\n", rs);//0,返回全局存储区中的s
printf("\n");
return 0;
}
运用结果:
5. 小结
(1)引用作为变量别名而存在,旨在代替指针
(2)const引用可以使得变量具有只读属性
(3)引用在编译器内部使用指针常量实现,其最终本质为指针
(4)引用可以尽可能的避开内存错误