对于一个完整的程序,其内存情况如下图:
图片来源:https://blog.csdn.net/u014470361/article/details/79297601
一、面向过程的static(位于函数内部)
当变量声明为static时,空间将在程序的生命周期内分配,其被存放在在全局数据区。即使多次调用该函数,静态变量的空间也只分配一次,前一次调用中的变量值通过下一次函数调用传递。
静态区(全局区):静态变量和全局变量的存储区域是一起的,一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放。
#include <iostream>
#include <string>
using namespace std;
void demo()
{
static int count = 0; // 静态变量
cout << count << " ";
count++;
}
int main()
{
for (int i=0; i<5; i++)
demo();
return 0;
}
输出为:
0 1 2 3 4
二、面向对象的static(位于类中)
2.1 静态成员变量
声明为static的变量只被初始化一次,因为它们在单独的静态存储中分配了空间,因此类中的静态变量由对象共享,可以减小对象的大小。对于不同的对象,不能有相同静态变量的多个副本。也是因为这个原因,静态变量不能使用构造函数初始化。
注意:类中的静态成员变量必须在类内声明,在类外定义(被const修饰的除外).
class Apple
{
public:
static int i; // 类内声明
Apple()
{
// Do nothing
};
};
int Apple::i = 1; // 类内定义
class Apple
{
public:
// 被const修饰的static变量在c++11中可以在类内被直接初始化。
static const int i=10;
Apple()
{
// Do nothing
};
};
2.2 静态成员函数
如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数。
静态成员函数有一个类范围,他们不能访问类的 this 指针。您可以使用静态成员函数来判断类的某些对象是否已被创建。
静态成员函数与普通成员函数的区别:
- 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
- 普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针。
下面的实例有助于更好地理解静态成员函数的概念:
#include <iostream>
using namespace std;
class Box
{
public:
static int objectCount;
// 构造函数定义
Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
// 每次创建对象时增加 1
objectCount++;
}
double Volume()
{
return length * breadth * height;
}
static int getCount()
{
return objectCount;
}
private:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
// 初始化类 Box 的静态成员
int Box::objectCount = 0;
int main(void)
{
// 在创建对象之前输出对象的总数
cout << "Inital Stage Count: " << Box::getCount() << endl;
Box Box1(3.3, 1.2, 1.5); // 声明 box1
Box Box2(8.5, 6.0, 2.0); // 声明 box2
// 在创建对象之后输出对象的总数
cout << "Final Stage Count: " << Box::getCount() << endl;
return 0;
}
当上面的代码被编译和执行时,它会产生下列结果:
Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2