引用和常量引用

来源:互联网 发布:淘宝天下传媒诈骗 编辑:程序博客网 时间:2024/06/05 06:58

引用(reference)用作对象的另一名字。在实际程序中,引用主要用作函数的形式参数。在这里,我们用独立的对象来介绍并举例说明引用的用法。

引用是一种复合类型(compound type),通过在变量名前添加“&”符号来定义。复合类型是指用其他类型定义的类型。在引用的情况下,每一种引用类型都“关联到”某一其他类型。不能定义引用类型的引用,但可以定义任何其他类型的引用。

引用必须用和该引用同类型的对象初始化:

int ival = 1024;int &refVal = ival; // ok: refVal refers to ivalint &refVal2; // error: a reference must be initializedint &refVal3 = 10; // error: initializer must be an object
  1. 引用是别名

因为引用只是它绑定的对象的另一名字,作用在引用上的所有操作事实上都是作用在该引用绑定的对象上:

refVal += 2;

将refVal指向的对象ival加2。类似地,

int ii = refVal;

把和ival相关联的值赋给ii。

当引用初始化后,只要该引用存在,它就保持绑定到初始化时指向的对象。不可能将引用绑定到另一个对象。

要理解的重要概念是引用只是对象的另一名字。事实上,我们可以通过ival的原名访问ival,也可以通过它的别名refVal访问。赋值只是另外一种操作,因此当我们编写

refVal = 5;

效果是把ival的值修改为5。这一规则的结果是必须在定义引用时进行初始化。初始化是指明引用指向哪个对象的唯一方法。

  1. 定义多个引用

可以在一个类型定义行中定义多个引用。必须在每个引用标识符前添加“&”符号:

int i = 1024, i2 = 2048;int &r = i, r2 = i2; // r is a reference, r2 is an intint i3 = 1024, &ri = i3; // defines one object, and one referenceint &r3 = i3, &r4 = i2; // defines two references
  1. const引用
const引用是指向const对象的引用:const int ival = 1024;const int &refVal = ival; // ok: both reference and object are constint &ref2 = ival; // error: nonconst reference to a const object

可以读取但不能修改refVal,因此,任何对refVal的赋值都是不合法的。这个限制有其意义:不能直接对ival赋值,因此不能通过使用refVal来修改ival。

同理,用ival初始化ref2也是不合法的:ref2是普通的非const引用(nonconst reference),因此可以用来修改ref2指向的对象的值。通过ref2对ival赋值会导致修改const对象的值。为阻止这样的修改,须要规定将普通的引用绑定到const对象是不合法的。

术语:const引用是指向const的引用

C++程序员常常随意地使用术语const引用。严格来说,“const引用”的意思是“指向const对象的引用”。类似地,程序员使用术语“非const引用”表示指向非const类型的引用。这种用法非常普遍,我们在本书中也遵循这种用法。

const引用可以初始化为不同类型的对象或者初始化为右值(2.3.1节),如字面值常量:

int i = 42;// legal for const references onlyconst int &r = 42;const int &r2 = r + i;

同样的初始化对于非const引用却是不合法的,而且会导致编译时错误。其原因非常微妙,值得解释一下。

观察将引用绑定到不同的类型时所发生的事情,最容易理解上述行为。假如我们编写

double dval = 3.14;const int &ri = dval;

编译器会把这些代码转换成如以下形式的编码:

int temp = dval; // create temporary int from the doubleconst int &ri = temp; // bind ri to that temporary

如果ri不是const,那么可以给ri赋一新值。这样做不会修改dval,而是修改了temp。期望对ri的赋值会修改dval的程序员会发现dval并没有被修改。仅允许const引用绑定到需要临时使用的值完全避免了这个问题,因为const引用是只读的。

非const引用只能绑定到与该引用同类型的对象。

const引用则可以绑定到不同但相关的类型的对象或绑定到左值。