" 引用 " 的 意义 :
引用 与 指针示例 : 下面的两个函数 , 分别使用 指针 和 引用 作为参数 ,
指针示例 :
// 交换 a 和 b 的值
// C 语言中可以使用该方法
void swap2(int* a, int* b)
{
int c = 0;
c = *a;
*a = *b;
*b = c;
}
引用示例 :
// 交换 a 和 b 的值
// C++ 中推荐的方法
void swap3(int& a, int& b)
{
int c = 0;
c = a;
a = b;
b = c;
}
在 C++ 语言中 , 用好引用 , 可以写出 高质量 , 高性能 , 高可读行 , 高可维护性 的代码 ;
在下面的代码中 , 先定义变量 a , 然后定义 已存在变量 a 的引用 b ;
// 定义变量 a
int a = 10;
// 定义变量 a 的引用 b
int& b = a;
定义 引用 时 ,
上述性质 , 类似于 " 常量 " , 说明 引用 具有 " 常量 " 的特征 ;
上述 int& b = a;
代码 , 如果使用 C 语言表达 , 就是
int* const b = &a;
定义的是一个指针常量 , 该指针是常量 , 指针本身 也就是 指针指向的地址 不可更改 ;
将上述 变量 a 和 引用 b 的地址 , 打印出来 ,
打印出的 变量 a 和 引用 b 的地址是相同的 , 说明这两个都是内存空间的别名 ;
代码如下 :
// 包含 C++ 头文件
#include "iostream"
// 使用 std 标准命名空间
// 该命名空间中 , 定义了很多标准定义
using namespace std;
// 导入 C 头文件
#include <stdio.h>
int main()
{
// 定义变量 a
int a = 10;
// 定义变量 a 的引用 b
int& b = a;
// 打印变量 a 和 引用 b 的地址
printf("&a = %d, &b = %d\n", &a, &b);
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
}
执行结果为 :
&a = 12516116, &b = 12516116
Press any key to continue . . .
引用 和 变量 都是相同的内存空间的别名 , 引用 本身 也占用内存空间 ,
引用 所占 的 内存空间 , 与 指针 所占的内存空间 是相同的 ;
验证 引用 所占的内存空间很简单 , 只需要在 结构体 中定义引用 , 然后获取该结构体的大小即可 ;
定义如下结构体 :
struct Student
{
int age;
int& a;
int& b;
};
使用 sizeof 函数 , 获取上述结构体的大小 ;
使用下面的代码验证 :
// 包含 C++ 头文件
#include "iostream"
// 使用 std 标准命名空间
// 该命名空间中 , 定义了很多标准定义
using namespace std;
// 导入 C 头文件
#include <stdio.h>
struct Student
{
int age;
int& a;
int& b;
};
int main()
{
printf("sizeof(Student) = %d\n", sizeof(Student));
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
}
执行结果 :
sizeof(Student) = 12
Press any key to continue . . .
上述 Student 结构体 , 占
字节的 内存空间 , int 类型已知占 4 字节 , 剩余的 引用 a 和 b 各占 4 字节 , 与指针所占的内存空间相同 ;
综合上述引用的特征 :
综合上面的三种特点 , C++ 语言编译器 中 , 引用的本质是 :
类型* const 指针名称;
指针 ;
引用在 C++ 语言内部是 常量指针 , 下面 C++ 语言的 " 引用 "
引用类型& 引用名称
等同于 下面的 C 语言的 " 常量指针 "
指针类型* const 指针名称
C++ 语言中的 引用 , 其在 编译器中的实现 就是 " 常量指针 " , 因此 引用 占用的内存空间与 指针 占用的内存空间 相同 ;
C++ 语言 为了提高 引用 的实用性 , 代码的可读性 , 隐藏了 引用 也会占用存储空间的 事实 , 该事实不会影响 开发者进行编程 , 只是对理解引用本质造成了困难 ;
C++ 语言中 的 函数中 , 使用 引用 作为函数参数 , 如下代码 :
void swap(int& a, int& b)
{
int c = 0;
c = a;
a = b;
b = c;
}
C++ 编译器编译上述代码时 , 会自动将上述代码翻译为 :
void swap(int* a, int* b)
{
int c = 0;
c = *a;
*a = *b;
*b = c;
}
在向 void swap(int* a, int* b)
函数 , 传入参数时 , 如果是 指针做参数 , 传入的参数必须是地址 , 需要开发者手动使用 取地址符 & 获取变量地址 , 传递给 函数 做实参 ;
在向 void swap(int& a, int& b)
函数 , 传入参数时 , 如果是 引用做参数 , 开发者 编写代码时 , 传入的是 int 类型变量的值 , C++ 编译器编译时 , 会自动在 int 类型变量前 添加 取地址符 , 不需要开发者 手动 使用 取地址符 & 获取变量地址 ;
显然 , 后者 开发难度 要小于 前者 ;
使用函数进行间接赋值 , 需要满足如下三个条件 :
如果将 函数 的形参类型 设置为 引用 类型 , 也能达到 间接赋值 的效果 ;
引用 实际上是 把 间接赋值 的三个条件的后两个条件进行了合并 , C++ 编译器遇到引用 , 还是需要将 引用 还原为 C 语言中的 取地址 传入函数 , 在函数内部使用指针访问实参 ;