static变量与全局变量有很多相似之处,下面是他们主要的异同点:
相同:1)都存储在静态存储区,相比之下局部变量是存储在程序栈中的。
2)生命周期与程序的生命周期相同,从初始化直到程序运行结束一直存在。而局部变量的使用周期只在它的定义域中(即所在的{}内)。
不同:全局变量的作用域就是全局,而静态成员的作用域有“局部性”,即稳健的作用域。
稳健的作用域是最难理解的地方,其实就是static变量同时具有全局变量和局部变量的性质。与全局变量相同的地方是生命周期,而与局部变量相同的是作用域。在一个函数内部定义的static变量在第一次定义的时候即存在,不会因为函数调用完毕而被销毁,下次调用该函数时该static变量已经存在,会跳过定义static变量的语句。static全局变量只能作用于定义它的文件里,不能作用到其他文件里。一般的全局变量可以使用extern关键字进行引用。
在类中定义的static成员变量和成员函数也具有一些独特的性质,在下面的程序里展现。
<pre name="code" class="cpp">/**
这个工程主要实现一些static的使用方法
*/
#include <iostream>
using namespace std;
/**在第一次调用fun函数时,value被定义,应为static对象只能被定义一次,
所以之后使用该函数时,会“跳过”定义static对象的语句!*/
void fun1(int i)
{
static int value = i; //该语句只在fun1第一次被调用时执行
cout << value << endl;
}
void fun2(int i)
{
static int value; //该语句只在fun1第一次被调用时执行
value = i; //赋值语句正常进行
cout << value << endl;
}
static int global_a = 0;
static void fun3()
{
cout << "static function" << endl;
}
/**sv只在第一次调用时被定义,之后调用改函数将掉过调用语句,
cv在每次调用时都被重新定义。*/
void fun4(int i)
{
static int sv = i;
const int cv = i;
cout << sv << " " << cv << endl;
}
class A
{
public:
static int pub;
static A a; //正确,可以在类内定义该类的static的实例
//A b; 错误,类A的定义不完整
A *pa; //正确,指针的大小是确定的
static void fun1() //正确,静态成员函数可以定义在类内,也可以定义在类外。在类外定义不能加static。
{
//++i; 错误,不能是用非静态成员!
++j;
cout << j << endl;
//cout << a.i << endl;
//cout << a.j << endl;
}
void fun2()
{
++i;
++j;
cout << i << " " << j << endl;
//cout << a.i << " " << a.j << endl;
}
private:
int i = 0;
//static int j = 0; 错误,不能在类的内部定义静态成员!
static int j; //在类内只能声明静态成员!
};
//在类外对静态成员进行定义,其目的是防止类的多个实例对static的重复定义!
int A::pub = 0;
int A::j = 0;
int main()
{
/**1: static 在一般函数中的使用方法。
注意static对象只能“定义”一次!*/
for(int i=0; i<5; ++i)
fun1(i); //输出5个0
for(int i=0; i<5; ++i)
fun2(i); //输出1 2 3 4 5
for(int i=0; i<5; ++i)
fun4(i);
/**2: static对象的定义与初始化问题,static对象在定义时可以不初始化,
这点与const对象不同,const对象必须在定义时初始化!*/
static int i;
i = 0;
/**3: static作为全局变量,与普通全局变量的区别是static全局变量只能初始化一次,
表示其他文件的不能引用这个static变量,该成员只对当前文件有效!
static函数是同样的道理!*/
cout << global_a << endl;
/**4: 类中的静态成员和静态成员函数(重点)。*/
cout << A::pub << endl; //正确,可以直接用类名调用类的public的static的成员变量。
cout << A::a.pub << endl;
A a, b;
a.fun1(); //输出1
b.fun1(); //输出2,具有一般静态成员的“记忆”功能
A::a.fun1(); //正确
//A::a.fun2(); //错误
return 0;
}
总之,理解static就是要理解它所定义的变量或函数的生命周期和作用范围(全局+局部)!
update: 2015-03-25,最近了解了一个static的新用法,就是在类内可以定义该类的static实例,而定义一般的该类的实例是不可以的!有什么作用呢?就是在主函数中可以不使用该类的实例来调用该类的static的成员函数,和使用static&public的成员变量。
update: 2015-03-31,这里对“该类的static实例”的理解有问题!在最新的博客“类内的static实例”进行了新的说明!