C++中提供了关键字static供我们使用,这个关键字可以用来修饰全局变量、局部变量、成员变量、成员方法和函数。它主要起到的作用是:限制被修饰的数据的作用域、生命周期。
static的作用域
作用域是指static所修饰的这个变量或者是函数是在哪个地方,例如:
(1) static修饰了全局变量serven,那么这个全局变量只能在这个文件Serven_Test.cpp使用,除了这个文件就失效了。
// Serven_Test1.cpp
#include <iostream>
using namespace std;
static int serven; // 定义了一个静态的全局变量
int main()
{
serven ++;
cout<<serven<<endl; // 程序运行结果是打印了 1
return 0;
}
(2) static在函数fun里面修饰局部变量serven,所以这个静态变量的作用域只局限于函数fun,除了这个函数就失效了,访问不了。
// Serven_Test2.cpp
#include <iostream>
using namespace std;
void fun()
{
static int serven; // 定义了一个静态的全局变量
serven ++;
cout<<serven<<endl;
}
int main()
{
fun();
// cout<<serven<<endl; // 程序运行结果是打印了 1
return 0;
}
利用作用域的特性可以在不同的文件中定义同名变量和同名函数,而不必担心命名冲突。
static的生命周期
生命周期是指,static修饰的变量或者函数在整个程序运行期间都存在,不会被释放掉,被修饰的变量或函数会在main函数之前就已经编译完成,直到程序运行结束后才会被释放。
static的共享性
共享性是指,变量定义后会在编译阶段编译好了,运行时候不会去给这个变量重新分配内存空间。
综合上面举个例子:
下面的代码中,变量serven_1和serven_2被static修饰,两个变量的作用域都在函数里面,可以看到第22行,在main函数中打印这个变量是出错的,但是这个变量又是陪伴这整个程序的生命周期的,当你再次调用Test_Static_1函数时,你会发现serven_1和serven_2的值会累加上去,还有一个特别注意的是,你可以静态变量可以不用初始化,如果没有初始化那么就会默认为0,并且变量会存储到内存区域的bss段;如果变量进行了初始化,那么变量会存储到内存区域的DATA段。为了比较普通的成员变量,我们定义了一个serven_2,在运行阶段调用到这个函数才会在内存的栈区域分配这个变量的区域大小,当调用完这个函数后就会把这个变量释放掉,下次进来再从新分配内存给这个变量。
// Serven_Test.cpp
#include <iostream>
using namespace std;
void Test_Staic_1(){
static int serven; // 如果不初始化值的话,就会默认初始化为0,该变量没有初始化,那么编译阶段就会存储在内存区域中的BSS段
static int serven_1 = 9; // 如果初始化该值,编译阶段就会将变量存储到内存区域的DATA段。
int serven_2 = 1; // 这是普通的成员变量,是在调用这个函数才会创建的,会存放在内存区域的栈,除了这个函数作用域就弹掉,没用了
serven ++;
serven_1 ++;
serven_2 ++;
cout<<"没有赋初始值:"<<serven<<" 有赋初始值:"<<serven_1<<" 普通成员变量:"<<serven_2<<endl;
}
void main(){
for (int i=0;i<5;i++)
{
Test_Staic_1();
//cout<<serven<<endl; // 这里打印就会出错,因为这里已经超出serven的作用域了,serven的作用域只限于Test_Static_Area函数
}
}
运行结果:
static修饰成员变量
在一个类中,static可以修饰该类的成员变量和成员方法,这些静态成员拥有一块单独的存储区,不管创建了多少个该类对象,所有的对象都共享这一块内存。静态成员本质上属于类,可以通过类名直接访问。还有一点就是静态成员方法只能访问静态成员变量,不能访问非静态成员变量。并且静态成员函数中没有this指针。
在一个团队合作一个项目中,为了避免每个程序员定义的变量冲突到,往往会使用static来修饰变量或者函数。