static在C++中算是一个低头不见抬头见的关键词了,使用比较频繁。粗略总结:
一、作用于全局变量
当static作用于全局变量,目的就是在其他源文件中隐藏当前的全局变量,只让当前定义该全局变量的源文件可以调用该全局变量。
有两个源文件,一个test.cpp 一个main.cpp,分别如下
//test.cpp,在该源文件中定义一个non-static的全局变量g_num并初始化一个值,无论g_num是static还是non-static的,在该源文件的func函数中是可以调用该全局变量的
#include <iostream>
using namespace std;
int g_num = 1;
void func()
{
cout << g_num << endl;
}
//main.cpp 因为g_num是non-static的全局变量,则在该源文件中也是可以调用到该全局变量的
#include <iostream>
using namespace std;
int main()
{
extern int g_num;
cout << g_num << endl;
return 0;
}
如果在全局变量的定义前限定为static类型,则在main.cpp中无法调用到该全局变量,因为此时就对除定义该全局变量的其他源文件隐藏该参数,无法调用。
二、作用于局部变量
作用于局部变量会延长该变量的生命周期,如果在一个作用域中定义一个non-static的局部变量,则在离开该作用域后,临时变量销毁,但是如果定义的为static的局部变量,则会存活在整个程序运行期间。
#include <iostream>
using namespace std;
int main()
{
for (int i = 0; i < 3; ++i)
{
int m_num = 1;
m_num++;
cout << m_num << endl;
}
system("pause");
return 0;
}
在main()中起一个for循环,并在进入循环的时候定义一个non-static的局部变量,则在每次循环结束该变量销毁,因此在每次进入for循环都会重新定义一个新的m_num,所以输出为
2
2
2
但是如果将m_num定义为static的局部变量
static int m_num = 1;
则在整个程序运行期间都是存在的。所以该输出为
2
3
4
为什么是这样一个结果呢,这和C++的内存分配有关系,
对于一个完整的程序,在内存中的分布情况如下图:
1.栈区: 由编译器自动分配释放,像局部变量,函数参数,都是在栈区。会随着作用于退出而释放空间。
3.堆区:程序员分配并释放的区域,像malloc©,new(c++)
3.全局数据区(静态区):全局变量和静态便令的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束释放。
4.代码区
所以static局部变量保存在全局数据区,和程序运行期一样存活,而non-static局部变量保存在栈区,寿命短没办法。
三、静态函数
普通函数按照全局变量来理解就好了,如果加上static后只能在当前源文件中被调用,这里主要讲讲类的静态成员函数。不被static修饰的类成员函数,在类被实例化后,可以被实例对象根据需要调用。
#include <iostream>
using namespace std;
class Car
{
public:
Car() {};
~Car() {};
void CreateWheel();
private:
};
void Car::CreateWheel()
{
cout << "the car need create 4 wheels" << endl;
}
int main()
{
Car *Audi = new Car;
Audi->CreateWheel();
system("pause");
return 0;
}
但是当对类的成员函数做static修饰,则不能通过实例化的Car对象调用,需要通过类名调用。可以理解为该成员函数的生存周期大于类的实例化对象。上面的例子改为
#include <iostream>
using namespace std;
class Car
{
public:
Car() {};
~Car() {};
static void CreateWheel();
private:
};
void Car::CreateWheel()
{
cout << "the car need create 4 wheels" << endl;
}
int main()
{
Car::CreateWheel();
system("pause");
return 0;
}
四、配合实现单例模式
其实可以归到第三类中讨论,但是单例是一种比较普遍使用的设计模式,所以单独拿出来讨论。即对类内实例化的对象进行static修饰。即类中的static变量会保证全局唯一,多个实例共享一个static变量,如果该static变量已经初始化过了,不会再次初始化,所以保证该类的实例只能是当前类内实例对象为类对象实例的唯一存在。
#include <iostream>
using namespace std;
class Car
{
public:
static Car* getInstance() {
if (instance == NULL)
{
instance = new Car();
}
return instance;
}
void CreateWheel();
private:
Car() {};
Car(const Car&);
~Car() {};
Car& operator =(const Car&);
private:
static Car* instance;
};
void Car::CreateWheel()
{
cout << "the car need create 4 wheels" << endl;
}
Car *Car::instance = NULL;
int main()
{
Car *Audi = Car::getInstance();
Audi->CreateWheel();
Car *BMW= Car::getInstance();
BMW->CreateWheel();
system("pause");
return 0;
}
其实调用的是一个CreateWheel,因为是一个代工厂。。。