2.2.4 名字的作用域
无论是在程序的什么位置,使用到的每个名字都会指向一个特定的实体:变量、函数、类型等。然而,同一个名字如果出现在程序的不同位置,也可能指向的是不同实体。
作用域(scope)是程序的一部分,在其中名字有其特定的含义。C++语言中大多数作用域都以花括号分隔。
同一个名字在不同的作用域中可能指向不同的实体。名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。
一个典型的示例来自于1.4.2节(第11页)的程序:
#include <iostream>
int main()
{
int sum = 0;
// sum用于存放从1到10所有数的和
for (int val = 1; val <= 10; ++val)
sum += val; // 等价于sum = sum + val
std::cout << "sum of 1 to 10 inclusive is " << sum << std::endl;
return 0;
}
这段程序定义了3个名字:main、sum和val,同时使用了命名空间名字std,该空间提供了2个名字cout和cin供系统使用。
名字main定义于所有花括号之外,它它其他大多数定义在函数体之外的名字一样拥有全局作用域(global scope)。一旦声明之后,全局作用域内的名字在整个程序的范围内都可使用。名字sum定义于main函数所限定的作用域之内,从声明sum开始知道main函数结束为止都可以访问它,但是出了main函数所在的块就无法访问了,因此说变量sum拥有块作用域(block scope)。名字val定义于for语句内,在for语句之内可以访问val,但是在main函数的其他部分就不能访问它了。
建议:当你第一次使用变量时再定义它
一般来说,在对象第一次被使用的地方附近定义它是一种好的选择,因为这样做有助于更容易地找到变量的定义。更重要的是,当变量的定义与它第一次被使用的地方很近时,我们也会赋给它一个比较合理的初始值。
嵌套的作用域
作用域能彼此包含,被包含(或者说被嵌套)的作用域称为内层作用域(inner scope),包含着别的作用域的作用域被称为外层作用域(outer scope)。
作用域中一旦声明了某个名字,它所嵌套着的所有作用域中都能访问该名字。同时,允许在内层作用域中重新定义外层作用域已有的名字:
#include <iostream>
// 该程序仅用于说明:函数内部不宜定义与全局变量同名的新变量
int reused = 42; // reused拥有全局作用域
int main()
{
int unique = 0; // unique拥有块作用域
// 输出#1:使用全局变量reused;输出42 0
std::cout << reused << " " << unique << std::endl;
int reused = 0; // 新建局部变量reused,覆盖了全局变量reused
// 输出#2:使用局部变量reused;输出0 0
std::cout << reused << " " << unique << std::endl;
// 输出#3:显式地访问全局变量reused;输出42 0
std::cout << ::reused << " " << unique << std::endl;
return 0;
}
输出#1出现在局部变量reused定义之前,因此这条语句使用全局作用域中定义的名字reused,输出42 0。输出#2发生在局部变量reused定义之后,此时局部变量reused正在作用域内(in scope),因此第二条输出语句使用的是局部变量reused而非全局变量,输出0 0。输出#3使用作用域操作符(参见1.2节,第七页)来覆盖默认的作用域规则,因为全局作用域本身并没有名字,所以当作用域操作符的左侧为空时,向全局作用域发出请求获取作用域操作符右侧名字对应的变量。结果是,第三条输出语句使用全局变量reused,输出42 0。
WARNING:如果函数有可能用到某些全局变量,则不宜再定义一个同名的局部变量。
普通的冒险故事提示您:看后求收藏(卧龙小说网http://www.wolongxs.com),接着再看更方便。
好书推荐:《我的剧本世界在自主运行》、《我是舰娘》、《交错世界之学院都市》、《认清现实后,她们开始追夫火葬场》、《剑来》、《好徒儿你就饶了为师伐》、《带着修真界仙子们天下无敌》、《修炼成仙的我只想养成女徒弟》、《足控勇者的目标是魔王的丝袜》、《被触手怪养大的少女》、