存储类别是变量的属性之一,C++语言中定义了4种变量的存储类别,分别是auto变量、static变量、register变量和extern变量。变量存储方式不同会使变量的生存期不同,生存期表示了变量存在的时间。生存期和变量作用域是从时间和空间这两个不同的角度来描述变量的特性。
静态存储变量通常是在变量定义时就分配固定的存储单元并一直保持不变,直至整个程序结束。前面讲过的全局变量即属于此类存储方式,它们存放在静态存储区中。动态存储变量是在程序执行过程中使用它时才分配存储单元,使用完毕立即将该存储单元释放。前面讲过的函数的形式参数,在函数定义时并不给形参分配存储单元,只是在函数被调用时才予以分配,调用函数完毕立即释放,此类变量存放在动态存储区中。从以上分析可知,静态存储变量是一直存在的,而动态存储变量则时而存在时而消失。
1.自动变量
这种存储类型是C++语言程序中默认的存储类型。函数内未加存储类型说明的变量均视为自动变量例如:
{
int i,j,k;
...
}
自动变量具有以下特点:
(1)自动变量的作用域仅限于定义该变量的个体内。在函数中定义的自动变量,只在该函数内有效。在复合语句中定义的自动变量只在该复合语句中有效。例如:
int Show()
{
int x,y;
if(true)
{
char ch;
cout << ch << endl; //正确
cout << x << endl; //正确
}
cout << ch << endl; //错误
cout << x << endl; //正确
}
(2)自动变量属于动态存储方式,变量分配的内存是在栈中,当函数调用结束后,自动变量的值会被释放。同样在复合语句中定义的自动变量,在退出复合语句后也不能再使用,否则将引起错误。
(3)由于自动变量的作用域和生存期都局限于定义它的个体内(函数或复合语句内),因此不同的个体中允许使用同名的变量而不会混淆。即使在函数内定义的自动变量也可与该函数内部的复合语句中定义的自动变量同名。
【例4.9】 输出不同生命期的变量值。
#include "stdafx.h"
#include<iostream>
using namespace std;
void main()
{
int i,j,k;
cout <<"input the number:" << endl;
cin >> i >> j;
k=i+j;
if( i!=0 && j!=0 )
{
int k;
k=i-j;
cout << "k :" << k << endl; //输出变量K的值
}
cout << "k :" <<k << endl; //输出变量k的值
}
程序运行结果如图4.13所示。
图4.13 输出不同生命期的变量值
程序两次输出变量k为自动变量。第一次输出的是i-j的值,第二次输出的是i+j的值。虽然变量名都为k,但其实是两个不同的变量。
注意:
在以前的标准中,关键字auto代表了自动变量的存储方式。在C++11的新标准中这一功能已经失效,在第10章中将详细介auto关键字的作用。
2.static变量
在声明变量前加关键字static,可以将变量声明成静态变量。静态局部变量的值在函数调用结束后不消失,静态全局变量只能在本源文件中使用。例如声明变量为静态变量:
static int a,b;
static float x,y;
static int a[3]={0,1,2};
静态变量属于静态存储方式,它具有以下特点:
(1)静态变量在函数内定义,在程序退出时释放,在程序整个运行期间都不释放,也就是说它的生存期为整个源程序。
(2)静态变量的作用域与自动变量相同,在函数内定义就在函数内使用,尽管该变量还继续存在,但不能使用它,如再次调用定义它的函数时,它又可继续使用。
(3)编译器会为静态局部变量赋予0值。
下面通过实例介绍static变量的用法。
【例4.10】 使用static变量实现累加。
#include "stdafx.h"
#include<iostream>
using namespace std;
int add(int x)
{
static int n=0;
n=n+x;
return n;
}
void main()
{
int i,j,sum;
cout << " input the number:" << endl;
cin >> i;
cout << "the result is:" << endl;
for(j=1;j<=i;j++)
{
sum=add(j);
cout << j << ":" <<sum << endl;
}
}
程序运行结果如图4.14所示。
图4.14 使用static变量实现累加
程序中n是静态局部变量,每次调用函数add时,静态局部变量n都保存了前次被调用后留下的值。所以当输入循环次数3时,变量sum累加的结果是6,而不是3。
如果去除static关键字,则运行结果如图4.15所示。
图4.15 运行结果
当输入循环次数3时,变量sum累加的结果是3。变量n不再使用静态存储区空间,每次调用后变量n的值都被释放,再次调用时n的值为初始值0。
3.register变量
通常变量的值存放在内存中,当对一个变量频繁读写时,需要反复访问内存储器,则花费大量的存取时间。为了提高效率,C++语言可以将变量声明为寄存器变量,这种变量将局部变量的值存放在CPU中的寄存器中,使用时不需要访问内存,而直接从寄存器中读写。寄存器变量的说明符是register。
对寄存器变量的说明:
(1)寄存器变量属于动态存储方式。凡需要采用静态存储方式的量不能定义为寄存器变量。
(2)编译程序会自动决定哪个变量使用寄存器存储。register起到程序优化的作用。
4.extern变量
在一个源文件中定义的变量和函数只能被本文件中的函数调用,一个C++程序中会有许多源文件,如果使用非本源文件的全局变量呢?C++提供了extern关键字来解决这个问题。在使用其他源文件的全局变量时,只需要在本源文件使用extern关键字来声明这个变量即可。例如
在Sample1.cpp源文件中定义全局变量a、b、c,代码如下。
int a,b; /*外部变量定义*/
char c; /*外部变量定义*/
vid main()
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
在Sample2.cpp源文件中要使用Sample1.cpp源文件中全局变量a、b、c,代码如下。
extern int a,b; /*外部变量说明*/
extern char c; /*外部变量说明*/
func (int x,y)
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
说明:
在第一章曾简单介绍过头文件,源文件的作用。在以后的章节中,将更加深入的探讨他们的使用方法 。
在Sample2.cpp源文件中,编译系统不再为全局变量a、b、c分配内存空间,而是改变全局变量a、b、c的值,在Sample1.cpp源文件中输出值也会发生变化。