3.5 作用域
作用域规则告诉我们一个变量的有效范围,它在哪里创建,在哪里销毁。变量的有效作用域从它的定义点开始,到和定义变量之前最邻近的开括号配对的第一个闭括号。即,作用域由变量所在的最近一对括号确定。
//:C03:Scope.cpp
// How variables are scoped
int main()
{
int scp1;
// scp1 visible here
{
// scp1 still visible here
int scp2;
// scp2 visible here
{
// scp1 & scp2 still visible here
int scp3;
// scp3 visible here
} // <-scp3 destroyed here
}// <-scp2 destroyed here
} // <-scp1 destroyed here
嵌套意味着可以再我们所处的作用域内访问外层作用域的一个变量。
实时定义变量:
C和C++有着显著的区别。这两种语言都要求变量使用前必须定义,但是C强制在作用域的开始处就定义所有的变量,以便在编译器创建一个块时,能给所有这些变量分配空间。
C++允许在作用域内的任意地方定义变量,所以可以再正好使用它之前定义。
还可以再for循环和while循环的控制表达式内定义变量,在if语句的条件表达式和switch的选择器语句内定义变量。
3.6 制定存储空间分配
3.6.1 全局变量
全局变量是在所有函数体的外部定义的,程序的所有部分都可以使用。全局变量不受作用域的影响,总是可用的。如果在一个文件中使用extern关键字来声明另一个文件中存在的全局变量,那么这个文件可以使用这个数据。
//:C03:Global.cpp
// {L} Global2
// Demonstration of global variables
#include <iostream>
using namespace std;
int globe;
void func();
int main()
{
globe = 12;
cout << globe << endl;
func();
cout << globe << endl;
}
下面的程序把globe作为一个外部变量来访问。
//:C03:Global2.cpp {o}
// Accessing external global variables
extern int globe;
void func()
{
globe = 47;
}
3.6.2 局部变量
局部变量出现在一个作用域内,它们是局限于一个函数的。局部变量经常被称为自动变量,因为它们在进入作用域时自动生成,离开作用域时自动消失。
3.6.2.1 寄存器变量
寄存器变量是一种局部变量。关键字register告诉编译器”尽可能快地访问这个变量“。
使用register变量是有限制的。不可能得到或计算register变量的地址。register变量只能在一个块中声明(不可能有全局的或静态的register变量)。然而可以再一个函数中使用register变量作为一个形式参数。
3.6.3 静态变量
函数中定义的局部变量在函数作用域结束时消失。当再次调用这个函数时,会重新创建该变量的存储空间。其值会被重新初始化。如果想使局部变量的值在程序的整个生命期里仍存在,可以定义函数的局部变量为static,并给它一个初始值。如:
//:C03:Static.cpp
// Using a static variable in a function
#include <iostream>
using namespace std;
void func()
{
static int i = 0;
cout << "i = " << ++i << endl;
}
int main()
{
for (int x = 0; x < 10; x++)
{
func();
}
return 0;
}
static的第二层意思是在某个作用域外不可访问。
3.6.4 外部变量
前面已经简要地描述和说明了extern关键字。它告诉编译器存在着一个变量和函数,即使编译器在当前编译的文件没有看到它。这个变量或函数可能在另一个文件中或者在当前文件的后面定义。例:
//: C03:Forward.cpp
// Forward function & data declarations
#include <iostream>
using namespace std;
extern int i;
extern void func();
int main()
{
i = 0;
func();
return 0;
}
int i; //The data definition
void func()
{
i++;
cout << i;
}
3.6.4.1 连接
在一个执行程序中,标识符代表存放变量或被编译过的函数体的存储空间。连接用连接器所见的方式描述存储空间。连接方式有两种:内部连接和外部连接。
内部连接意味着只对正被编译的文件创建存储空间。用内部连接,别的文件可以使用相同的标识符或全局变量,连接器不会发现冲突。内部连接由关键字static指定。
外部连接意味着为所有被编译过的文件创建一片单独的存储空间。一旦创建存储空间,连接器必须解决所有对这片存储空间的引用。通过用关键字extern声明。
调用函数时,自动变量只是临时存在于堆栈中。
3.6.5 常量
C++引入了命名常量的概念,命名常量就像变量一样,值是它的值不能改变。修饰符const告诉编译器这个名字表示一个常量。
C++中,一个const必须有初始值。
3.6.6 volatile变量
限定词const告诉编译器“这是不会改变的”;而限定词volatile则告诉编译器“不知道什么时候会改变”,防止编译器依据变量的稳定性作任何优化。