跳转到内容

2.6 初识名字查找

在前面作用域的介绍中,有这样的一段示例代码:

int sub_mul(int a, int b, int c) {
int diff = a - b;
return diff * c;
}
a = 1; // 错误:a在这里都是不可见的

但是,如果外面有一个全局变量 a,那么这段代码就是正确的:

int a = 1; // 全局变量 a
int sub_mul(int a, int b, int c) {
int diff = a - b;
return diff * c;
}
a = 1; // 正确:这里被访问的是全局变量 a

实际上,对于所有嵌套的作用域,内部的名字都会覆盖外部作用域中的名字。例如:

int a = 1; // a1
{
int a = 2; // a2
{
int a = 3; // a3
a += 1; // 在这里,a 是内部的 a3
}
a += 1; // 在这里,a 是 a2
}
a += 1; // 在这里,a 是 a1

这样内部可以覆盖外部的设计,让局部代码不需要关心和全局变量的冲突,显著减少了程序员的心智负担。但是,考虑如下的情况:

int a = 1;
{
int a = 2;
{
a += 1; // 这里的 a 是哪个呢?
}
}

这里的 a 是哪个呢?

以目前讲述过的概念而言,读者可以用下面的规则来理解名字查找的过程:

  1. 声明必须在使用之前。
  2. 从下往上查找,在当前作用域找不到的话,到外层作用域继续向上查找。
  3. 如果一个名字找到至少一个对应的声明,就停止查找。

例如,前面的问题中:

int a = 1; // a1
{
int a = 2; // a2
{
a += 1; // 这里的 a 是 a2
}
}

名字查找只会向上查找,在如下的代码中:

int a = 1; // a1
{
{
a += 1; // 这里的 a 是 a1
int a = 2; // a2
}
int a = 3; // a3
}

虽然后面的两个 a 在更内层的作用域中声明,但是在使用的时候,查找的过程是从下往上的,所以这里 a += 1; 中的 a 是外层的 a。

:::