Team LiB
Previous Section Next Section

2.5. References

2.5. 引用

A reference serves as an alternative name for an object. In real-world programs, references are primarily used as formal parameters to functions. We'll have more to say about reference parameters in Section 7.2.2 (p. 232). In this section we introduce and illustrate the use of references as independent objects.

引用就是对象的另一个名字。在实际程序中,引用主要用作函数的形式参数。我们将在第 7.2.2 节 再详细介绍引用参数。在这一节,我们用独立的对象来介绍并举例说明引用的用法。

A reference is a compound type that is defined by preceding a variable name by the & symbol. A compound type is a type that is defined in terms of another type. In the case of references, each reference type "refers to" some other type. We cannot define a reference to a reference type, but can make a reference to any other data type.

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

A reference must be initialized using an object of the same type as the reference:

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

      int ival = 1024;
      int &refVal = ival; // ok: refVal refers to ival
      int &refVal2;       // error: a reference must be initialized
      int &refVal3 = 10;  // error: initializer must be an object

A Reference Is an Alias

引用是别名

Because a reference is just another name for the object to which it is bound, all operations on a reference are actually operations on the underlying object to which the reference is bound:

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

      refVal += 2;

adds 2 to ival, the object referred to by refVal. Similarly,

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

      int ii = refVal;

assigns to ii the value currently associated with ival.

把和 ival 相关联的值赋给 ii

When a reference is initialized, it remains bound to that object as long as the reference exists. There is no way to rebind a reference to a different object.

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

The important concept to understand is that a reference is just another name for an object. Effectively, we can access ival either through its actual name or through its alias, refVal. Assignment is just another operation, so that when we write

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

      refVal = 5;

the effect is to change the value of ival to 5. A consequence of this rule is that you must initialize a reference when you define it; initialization is the only way to say to which object a reference refers.

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

Defining Multiple References

定义多个引用

We can define multiple references in a single type definition. Each identifier that is a reference must be preceded by the & symbol:

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

      int i = 1024, i2 = 2048;
      int &r = i, r2 = i2;      // r is a reference, r2 is an int
      int i3 = 1024, &ri = i3;  // defines one object, and one reference
      int &r3 = i3, &r4 = i2;   // defines two references

const References

const 引用

A const reference is a reference that may refer to a const object:

const 引用是指向 const 对象的引用:

      const int ival = 1024;
      const int &refVal = ival;      // ok: both reference and object are const
      int &ref2 = ival;              // error: non const reference to a const object

We can read from but not write to refVal. Thus, any assignment to refVal is illegal. This restriction should make sense: We cannot assign directly to ival and so it should not be possible to use refVal to change ival.

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

For the same reason, the initialization of ref2 by ival is an error: ref2 is a plain, nonconst reference and so could be used to change the value of the object to which ref2 refers. Assigning to ival through ref2 would result in changing the value of a const object. To prevent such changes, it is illegal to bind a plain reference to a const object.

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

Terminology: const Reference is a Reference to const

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

C++ programmers tend to be cavalier in their use of the term const reference. Strictly speaking, what is meant by "const reference" is "reference to const." Similarly, programmers use the term "nonconst reference" when speaking of reference to a nonconst type. This usage is so common that we will follow it in this book as well.

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


A const reference can be initialized to an object of a different type or to an rvalue (Section 2.3.1, p. 45), such as a literal constant:

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

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

The same initializations are not legal for nonconst references. Rather, they result in compile-time errors. The reason is subtle and warrants an explanation.

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

This behavior is easiest to understand when we look at what happens when we bind a reference to an object of a different type. If we write

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

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

the compiler transforms this code into something like this:

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

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

If ri were not const, then we could assign a new value to ri. Doing so would not change dval but would instead change temp. To the programmer expecting that assignments to ri would change dval, it would appear that the change did not work. Allowing only const references to be bound to values requiring temporaries avoids the problem entirely because a const reference is read-only.

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

A nonconst reference may be attached only to an object of the same type as the reference itself.

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


A const reference may be bound to an object of a different but related type or to an rvalue.

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

Exercises Section 2.5

Exercise 2.24:

Which of the following definitions, if any, are invalid? Why? How would you correct them?

下列哪些定义是非法的?为什么?如何改正?

     (a) int ival = 1.01;     (b) int &rval1 = 1.01;
     (c) int &rval2 = ival;   (d) const int &rval3 = 1;

Exercise 2.25:

Given the preceeding definitions, which, if any, of the following assignments are invalid? If they are valid, explain what they do.

在上题给出的定义下,下列哪些赋值是非法的?如果赋值合法,解释赋值的作用。

     (a) rval2 = 3.14159;  (b) rval2 = rval3;
     (c) ival = rval3;     (d) rval3 = ival;

Exercise 2.26:

What are the differences among the definitions in (a) and the assignments in (b)? Which, if any, are illegal?

(a) 中的定义和 (b) 中的赋值存在哪些不同?哪些是非法的?

     (a) int ival = 0;          (b) ival = ri;
         const int &ri = 0;         ri = ival;

Exercise 2.27:

What does the following code print?

下列代码输出什么?

     int i, &ri = i;
     i = 5; ri =10;
     std::cout << i << " " << ri << std::endl;

Team LiB
Previous Section Next Section