基本使用
int i = 0; int& a = i, &b = i;
void foo2(int& a)
{
a++;
}
int main() {
int a = 1;
foo2(a);
}
使用一个对象来初始化引用,而不是使用值来初始化引用。
在C++中,引用可以狭义地认为是某一个变量的别名,但是不要认为引用是 C++ 编译器在编译时的一些黑魔法。可能“别名”这个词会有这样的误解,它在运行的时候将两个解析到的符号链接成了一个,从而完成了引用,而在编译之后,引用与本体就是一个变量(一个寄存器或栈上的值)。但是实际上引用是通过指针来实现的。
引用的实现
实际上,引用本身是一个变量,只不过这个变量的定义和使用与普通变量有显著的不同。
int i=5;
int &ri=i;
ri=8;
// 汇编
int i=5;
00A013DE mov dword ptr [i],5 //将文字常量5送入变量i
int &ri=i;
00A013E5 lea eax,[i] //**将变量i的地址送入寄存器eax**
00A013E8 mov dword ptr [ri],eax //将寄存器的内容(也就是变量i的地址)送入变量ri
ri=8;
00A013EB mov eax,dword ptr [ri] //将变量ri的值送入寄存器eax
00A013EE mov dword ptr [eax],8 //将数值8送入以eax的内容为地址的单元中
return 0;
00A013F4 xor eax,eax
看出 ri 是实际存在着的变量,如果引用只是某一个变量的别名的话,那么最终生成的代码将不会存在 ri 这个变量。
int i=5;
int* const pi=&i;
*pi=8;
// 汇编
int i=5;
011F13DE mov dword ptr [i],5
int * const pi=&i;
011F13E5 lea eax,[i]
011F13E8 mov dword ptr [pi],eax
*pi=8;
011F13EB mov eax,dword ptr [pi]
011F13EE mov dword ptr [eax],8
将pi换成ri,所得汇编代码与第一段所对应的汇编代码完全一样。所以,引用变量在功能上等于一个指针常量,即一旦指向某一个单元就不能在指向别处。
什么是引用
引用可以被认为是带有自动解引用功能的指针常量,即编译器将为你应用*操作符。
使用时注意事项
所有引用必须用非空值初始化,否则编译将失败。引用不可以被重新赋值。
无法获取引用的地址—地址操作符将返回被引用值的地址—也不可能对引用进行算术运算。
如果一个函数的作用是创建一个对象,那么在不确定一个对象是否创建成功,使用指针,因为将 NULL 赋值给引用会导致奔溃。