1、分类及作用域
变量可以分为全局变量、静态全局变量、静态局部变量和局部变量。
按存储区域分:全局变量、静态全局变量和静态局部变量都存放在内存的全局数据区,局部变量存放在内存的栈区。
按作用域分:全局变量在整个工程文件内都有效(通过extern int a; 来跨文件使用);静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。
全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知。
2、释放顺序
在局部变量中,我们知道变量是存放在栈中的,所以变量的释放次序应该是后声明的先释放内存,现在我们看一看全局变量之间,以及全局变量与静态变量之间的内存释放顺序:
#include <iostream>
using namespace std;
int a;
class A {
public :
A(int x){
tmp = x;
cout << "tmp : " << tmp << endl;
}
~A(){
cout << "tmp " << tmp << endl;
}
private :
int tmp;
};
A a1(1); // 全局变量;
static A a2(2);
A a3(3);
int main()
{
A a4(4);//局部变量;
static A a5(5);//静态局部变量;
static A a6(6);
return 0;
}
编译结果如下:
从中可以看到:局部变量的释放先于全局变量和静态变量,而静态变量之间,全局变量之间的以及静态变量与全局变量之间的内存释放顺序依然遵循后声明先释放的次序。
3、全局变量定义在头文件中会引起什么问题?
最近发现,有些刚入门的同学在头文件中定义了全局变量,链接报错重定义。
一般来讲,全局变量一定要定义在.c文件中,比如int g_int=0;,然后头文件extern int g_int,老司机差不多都这样写,这样某个地方(其它源文件)中需要用到该全局变量就把这个头文件包含进去,或者在其它源文件中直接extern int g_int,可千万不要将全局变量定义在头文件中,如果定义在头文件中,包含了这个头文件的文件都会在预处理的时候展开这个头文件,相当于在这里又定义了一个int g_int=0;链接的时候就会出错。
另外,在一些编译器中会提示你加static,当你在头文件中定义全局变量的时候,加了static的全局变量表示只在该源文件中有效,不管是.h还是.c,所以你某个源文件中能编译通过,在使用的时候发现,这个全局变量地址怎么不一样,这就是因为加了static的缘故,相当于你在两个原文件中分别定义了static的同名变量,因为static修饰作用,不会重名报错,但是很有可能跟你初始想法就不一样了。
所以最后记得千万不要在头文件中定义全局变量,而要在.c文件中定义,如果全局变量特别多,上百个,可以专门用一个头文件来引入这些全局变量,也就是一个头文件专门:
extern int g_int=0;
extern float g_float=0.0f;
.........
然后在用的地方直接导入该头文件就可以了,不用在每个用的地方专再重复extern了。