1. 静态变量
1.1 函数中的静态局部变量
当变量声明为static时,变量的空间将在程序的生命周期内分配。即使多次调用该函数,静态变量的空间也只分配一次,函数调用结束,变量不被销毁。这对于需要存储先前函数状态的程序非常有用。
1.2 静态全局变量
用static修饰的全局变量只能在本文件内访问,因此static具有限定访问范围的作用。
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include "iostream"
using namespace std;
int a = 10;
void msg() { cout << "Hello World" << endl; }
#include <iostream>
using namespace std;
int main(void) { extern int a; cout << a << endl; extern void msg(); msg(); return 0; }
|
程序运行结果如下:
由于test1.cpp中定义的全局变量a和函数msg没有被static修饰,具有全局可见性,所以在main.cpp中可以访问。如果使用static修饰:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include "iostream"
using namespace std;
static int a = 10;
static void msg() { cout << "Hello World" << endl; }
#include <iostream>
using namespace std;
int main(void) { extern int a; cout << a << endl; extern void msg(); msg(); return 0; }
|
运行程序,会报如下错误:
无法访问test1.cpp中定义的变量a和函数msg,因此报错。
1.3 类中的静态变量
声明为static的变量只被初始化一次。
由于它们在单独的静态存储中分配了空间,因此类中的静态变量由对象共享。
对于不同的对象,不能有相同静态变量的多个副本。因为此,静态变量不能使用构造函数初始化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Apple { public: static int count; };
#include <iostream> #include "test1.cpp"
using namespace std;
int Apple::count = 0;
int main() { Apple obj1; Apple obj2; obj1.count = 1; obj2.count = 2; cout << "obj1.count: " << obj1.count << endl << "obj2.count: " << obj2.count << endl; }
|
上述main.cpp的输出为:
可以看到Apple类的静态变量count为多个对象共享,一个对象改变其值,所有对象的值都发生改变。
2. 静态成员
2.1 类对象为静态
与变量类似,类实例化的对象也有生命周期,考虑如下程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
#include "iostream"
using namespace std;
class Apple { public: Apple() { cout << "Inside Constructor" << endl; }
~Apple() { cout << "Inside Destructor" << endl; } };
#include <iostream> #include "test1.cpp"
using namespace std;
int main() { int x = 0; if (x == 0) { Apple obj; } cout << "End of main" << endl; }
|
程序运行结果如下:
在上面的程序中,对象在if代码块内声明,且为非静态对象,则该变量的生命周期仅在if代码块内。当进入if代码块时,创建对象并调用构造函数,并且在if代码块结束的时候调用析构函数销毁对象。
如果将对象声明为静态:
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <iostream> #include "test1.cpp"
using namespace std;
int main() { int x = 0; if (x == 0) { static Apple obj; } cout << "End of main" << endl; }
|
结果如下所示:
由于static对象的声明周期为整个程序,因此在main函数结束时对象才会销毁。
2.2 类中的静态函数
与类中的静态数据成员和静态变量一样,静态成员函数也不依赖于类的对象。
可以使用对象和运算符“.”调用静态成员函数,但建议使用类名和范围解析运算符调用静态成员。
静态成员函数仅可以访问静态数据成员或其他静态成员函数,无法访问类的非静态成员。
本文为学习C++那些事 (github.com)所记笔记。