基本使用

  1. int i = 0; int& a = i, &b = i;
  2. void foo2(int& a)
  3. {
  4. a++;
  5. }
  6. int main() {
  7. int a = 1;
  8. foo2(a);
  9. }

使用一个对象来初始化引用,而不是使用值来初始化引用。

在C++中,引用可以狭义地认为是某一个变量的别名,但是不要认为引用是 C++ 编译器在编译时的一些黑魔法。可能“别名”这个词会有这样的误解,它在运行的时候将两个解析到的符号链接成了一个,从而完成了引用,而在编译之后,引用与本体就是一个变量(一个寄存器或栈上的值)。但是实际上引用是通过指针来实现的。

引用的实现

实际上,引用本身是一个变量,只不过这个变量的定义和使用与普通变量有显著的不同。

  1. int i=5;
  2. int &ri=i;
  3. ri=8;
  4. // 汇编
  5. int i=5;
  6. 00A013DE mov dword ptr [i],5 //将文字常量5送入变量i
  7. int &ri=i;
  8. 00A013E5 lea eax,[i] //**将变量i的地址送入寄存器eax**
  9. 00A013E8 mov dword ptr [ri],eax //将寄存器的内容(也就是变量i的地址)送入变量ri
  10. ri=8;
  11. 00A013EB mov eax,dword ptr [ri] //将变量ri的值送入寄存器eax
  12. 00A013EE mov dword ptr [eax],8 //将数值8送入以eax的内容为地址的单元中
  13. return 0;
  14. 00A013F4 xor eax,eax

看出 ri 是实际存在着的变量,如果引用只是某一个变量的别名的话,那么最终生成的代码将不会存在 ri 这个变量。

  1. int i=5;
  2. int* const pi=&i;
  3. *pi=8;
  4. // 汇编
  5. int i=5;
  6. 011F13DE mov dword ptr [i],5
  7. int * const pi=&i;
  8. 011F13E5 lea eax,[i]
  9. 011F13E8 mov dword ptr [pi],eax
  10. *pi=8;
  11. 011F13EB mov eax,dword ptr [pi]
  12. 011F13EE mov dword ptr [eax],8

将pi换成ri,所得汇编代码与第一段所对应的汇编代码完全一样。所以,引用变量在功能上等于一个指针常量,即一旦指向某一个单元就不能在指向别处。

什么是引用

引用可以被认为是带有自动解引用功能的指针常量,即编译器将为你应用*操作符。

使用时注意事项

  • 所有引用必须用非空值初始化,否则编译将失败。引用不可以被重新赋值。

  • 无法获取引用的地址—地址操作符将返回被引用值的地址—也不可能对引用进行算术运算。

  • 如果一个函数的作用是创建一个对象,那么在不确定一个对象是否创建成功,使用指针,因为将 NULL 赋值给引用会导致奔溃。