Team LiB
Previous Section Next Section

2.4. const Qualifier

2.4. const 限定符

There are two problems with the following for loop, both concerning the use of 512 as an upper bound.

下列 for 循环语句有两个问题,两个都和使用 512 作为循环上界有关。

      for (int index = 0; index != 512; ++index) {
          // ...

The first problem is readability. What does it mean to compare index with 512? What is the loop doingthat is, what makes 512 matter? (In this example, 512 is known as a magic number, one whose significance is not evident within the context of its use. It is as if the number had been plucked by magic from thin air.)

第一个问题是程序的可读性。比较 index 与 512 有什么意思呢?循环在做什么呢?也就是说 512 作用何在?[本例中,512 被称为魔数(magic number,它的意义在上下文中没有体现出来。好像这个数是魔术般地从空中出现的。

The second problem is maintainability. Imagine that we have a large program in which the number 512 occurs 100 times. Let's further assume that 80 of these references use 512 to indicate the size of a particular buffer but the other 20 use 512 for different purposes. Now we discover that we need to increase the buffer size to 1024. To make this change, we must examine every one of the places that the number 512 appears. We must determinecorrectly in every casewhich of those uses of 512 refer to the buffer size and which do not. Getting even one instance wrong breaks the program and requires us to go back and reexamine each use.

第二个问题是程序的可维护性。假设这个程序非常庞大,512 出现了 100 次。进一步假设在这 100 次中,有 80 次是表示某一特殊缓冲区的大小,剩余 20 次用于其他目的。现在我们需要把缓冲区的大小增大到 1024。要实现这一改变,必须检查每个 512 出现的位置。我们必须确定(在每种情况下都准确地确定)哪些 512 表示缓冲区大小,而哪些不是。改错一个都会使程序崩溃,又得回过头来重新检查。

The solution to both problems is to use an object initialized to 512:

解决这两个问题的方法是使用一个初始化为 512 的对象:

      int bufSize = 512;    // input buffer size
      for (int index = 0; index != bufSize; ++index) {
          // ...

By choosing a mnemonic name, such as bufSize, we make the program more readable. The test is now against the object rather than the literal constant:

通过使用好记的名字如 bufSize,增强了程序的可读性。现在是对对象 bufSize 测试而不是字面值常量 512 测试:

      index != bufSize

If we need to change this size, the 80 occurrences no longer need to be found and corrected. Rather, only the one line that initializes bufSize requires change. Not only does this approach require significantly less work, but also the likelihood of making a mistake is greatly reduced.

现在如果想要改变缓冲区大小,就不再需要查找和改正 80 次出现的地方。而只有初始化 bufSize 那行需要修改。这种方法不但明显减少了工作量,而且还大大减少了出错的可能性。

Defining a const Object

定义 const 对象

There is still a serious problem with defining a variable to represent a constant value. The problem is that bufSize is modifiable. It is possible for bufSize to be changedaccidentally or otherwise. The const type qualifier provides a solution: It transforms an object into a constant.

定义一个变量代表某一常数的方法仍然有一个严重的问题。即 bufSize 是可以被修改的。bufSize 可能被有意或无意地修改。const 限定符提供了一个解决办法,它把一个对象转换成一个常量。

      const int bufSize = 512;     // input buffer size

defines bufSize to be a constant initialized with the value 512. The variable bufSize is still an lvalue (Section 2.3.1, p. 45), but now the lvalue is unmodifiable. Any attempt to write to bufSize results in a compile-time error.

定义 bufSize 为常量并初始化为 512。变量 bufSize 仍然是一个左值(第 2.3.1 节),但是现在这个左值是不可修改的。任何修改 bufSize 的尝试都会导致编译错误:

      bufSize = 0; // error: attempt to write to const object

Because we cannot subsequently change the value of an object declared to be const, we must initialize it when it is defined:


      const std::string hi = "hello!"; // ok: initialized
      const int i, j = 0;  // error: i is uninitialized const

const Objects Are Local to a File By Default

const 对象默认为文件的局部变量

When we define a nonconst variable at global scope (Section 2.3.6, p. 54), it is accessible throughout the program. We can define a nonconst variable in one file andassuming an appropriate declaration has been madecan use that variable in another file:

在全局作用域(第 2.3.6 节)里定义非 const 变量时,它在整个程序中都可以访问。我们可以把一个非 const 变更定义在一个文件中,假设已经做了合适的声明,就可在另外的文件中使用这个变量:

      int counter;  // definition
      extern int counter; // uses counter from file_1
      ++counter;          // increments counter defined in file_1

Unlike other variables, unless otherwise specified, const variables declared at global scope are local to the file in which the object is defined. The variable exists in that file only and cannot be accessed by other files.

与其他变量不同,除非特别说明,在全局作用域声明的 const 变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。

We can make a const object accessible throughout the program by specifying that it is extern:

通过指定 const 变更为 extern,就可以在整个程序中访问 const 对象:

      // defines and initializes a const that is accessible to other files
      extern const int bufSize = fcn();
      extern const int bufSize; // uses bufSize from file_1
      // uses bufSize defined in file_1
      for (int index = 0; index != bufSize; ++index)
            // ...

In this program, defines and initializes bufSize to the result returned from calling the function named fcn. The definition of bufSize is extern, meaning that bufSize can be used in other files. The declaration in is also made extern. In this case, the extern signifies that bufSize is a declaration and hence no initializer is provided.

本程序中, 通过函数 fcn 的返回值来定义和初始化 bufSize。而 bufSize 定义为 extern,也就意味着 bufSize 可以在其他的文件中使用。file_2.ccextern 的声明同样是 extern;这种情况下,extern 标志着 bufSize 是一个声明,所以没有初始化式。

We'll see in Section 2.9.1 (p. 69) why const objects are made local to a file.

我们将会在第 2.9.1 节看到为何 const 对象局部于文件创建。

Nonconst variables are extern by default. To make a const variable accessible to other files we must explicitly specify that it is extern.

const 变量默认为 extern。要使 const 变量能够在其他的文件中访问,必须地指定它为 extern

Exercises Section 2.4

Exercise 2.22:

The following program fragment, while legal, is an example of poor style. What problem(s) does it contain? How would you improve it?


      for (int i = 0; i < 100; ++i)
          // process i

Exercise 2.23:

Which of the following are legal? For those usages that are illegal, explain why.


      (a) const int buf;
      (b) int cnt = 0;
          const int sz = cnt;
      (c) cnt++; sz++;

Team LiB
Previous Section Next Section