1、首先,总结一下c/c++程序内存构成:
一个程序被加载到内存中,这块内存首先就存在两种属性:静态分配内存和动态分配内存。
静态分配内存:是在程序编译和链接时就确定好的内存。
动态分配内存:是在程序加载、调入、执行的时候分配/回收的内存。
1.1静态内存区:静态/全局区、代码区、常量区
-
静态/全局区: 存放全局变量、静态变量以及const常量。
-
文字常量区: 常量字符串存放于此,程序结束后由系统释放。
-
代码区: 用来存放程序执行代码。
这三段内存就组成了我们编写的程序的本体,但是一个程序运行起来,还需要更多的数据和数据间的交互,否则这个程序就是死的,无用的。所以我们还需要为更多的数据和数据交互提供一块内存——堆栈。
1.2动态存储区:堆区(heap)、栈区(stack)
-
栈区(stack): 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
-
堆区(heap): 一般由程序员分配释放,对于的操作有new和delete、free和malloc, 若程序员不释放,程序结束时可能由OS回收。
堆和栈都是动态分配内存,两者空间大小都是可变的。
2、C 语言的 static :
2.1 静态全局变量
静态全局变量有以下特点:
a• 该变量在静态/全局区分配内存;
b• 未经初始化的静态全局变量会被程序自动初始化为0;
c• 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的;
一般静态全局变量定义在.cpp文件中,只能被该cpp文件使用,不能被其他文件使用。
声明、定义在.h文件中的静态全局变量,被其他.cpp文件include、使用时,每被其他文件include一次,就会被声明、定义一次,在不同模块中该变量虽然变量名相同,但是在内存中的地址不同,不是同一个变量,只是名字相同而已。
.cpp文件在使用.h文件中的全局变量时,需在cpp文件中使用extern关键字对.h全局变量进行声明。
2.2静态局部变量
静态局部变量有以下特点:
a• 该变量在静态/全局区分配内存;
b• 函数结束时,静态局部变量不会消失,每次该函数调用时也不会为其重新分配空间;
c• 静态局部变量在只在局部变量作用域范围内有效,超过作用域不能使用;
2.3静态函数
一般情况下,建议在.cpp文件中声明、定义静态函数
2.3.1定义在.h文件中的静态函数
定义在头文件中的static函数,和普通函数没有很大的区别的。
唯一的区别就是,在调用该函数的时候,static函数在内存中只维持一份,而普通函数每次调用都会维持一份拷贝。
当然这个静态函数也可以在其他文件中调用了!只是要包含它所在的头文件了。
2.3.1定义在.cpp文件中的静态函数
a• 定义在cpp文件中的静态函数,这个函数只能在本文件中使用,不能被其他文件使用;
b• 其他cpp文件定义相同函数名不会引起冲突,能编译通过;
3、C++ 语言的 static :
3.1静态成员变量
用于修饰 class 的数据成员,即所谓“静态成员”。这种数据成员的生存期大于 class 的对象(实体 instance)。静态数据成员是每个 class 有一份,普通数据成员是每个 instance 有一份,因此静态数据成员也叫做类变量,而普通数据成员也叫做实例变量。
3.2静态成员函数
不必生成类的实例化对象,可以用类名::函数名进行访问,静态成员函数具有如下特点:
a.静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
b.非静态成员函数可以任意地访问静态成员函数和静态数据成员;
c.静态成员函数不能访问非静态成员函数和非静态数据成员;
d.调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数,也可以用类名::函数名调用。class.静态成员函数不能访问非静态成员函数和非静态数据成员;
e.静态成员函数没有this指针;
f.静态成员函数不能是虚函数。