C/C++ 中 static 关键字详解
static 是 C/C++ 中一个非常重要的关键字,用途灵活。它既可以修饰全局变量,也可以修饰局部变量和函数。在 C++ 中还可以修饰类成员变量和成员函数。本文将从不同角度详细讲解 static 的作用、生命周期和使用场景。
1. static 修饰全局变量
示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | #include <stdio.h>
 static int counter = 0;
 
 void add() {
 counter++;
 printf("counter = %d\n", counter);
 }
 
 int main() {
 add();
 add();
 add();
 return 0;
 }
 
 | 
特点
- 生命周期:和普通全局变量一样,从程序开始到程序结束。
- 作用域:仅在当前源文件可见,无法通过 extern在其他文件访问。
- 多次访问:变量值会一直保留,不会因为函数调用结束而销毁。
对比普通全局变量
| 特性 | 普通全局变量 | static全局变量 | 
| 生命周期 | 整个程序运行期间 | 整个程序运行期间 | 
| 作用域 | 跨文件可见 | 当前文件可见 | 
| 初始化次数 | 程序启动时一次 | 程序启动时一次 | 
| 多次访问效果 | 同一份存储空间,值累积 | 同一份存储空间,值累积 | 
使用 static 修饰全局变量可以避免命名冲突,增强封装性。
2. static 修饰局部变量
示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | #include <stdio.h>
 void demo() {
 static int count = 0;
 count++;
 printf("count = %d\n", count);
 }
 
 int main() {
 demo();
 demo();
 demo();
 return 0;
 }
 
 | 
特点
- 生命周期:从程序开始到程序结束,与全局变量一样。
- 作用域:仅在定义的函数内部可见。
- 多次访问:每次调用函数时,变量不会重新初始化,保留上一次的值。
3. static 修饰函数
示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | #include <stdio.h>
 static void hello() {
 printf("Hello, static function!\n");
 }
 
 int main() {
 hello();
 return 0;
 }
 
 | 
特点
- 作用域:仅在定义的源文件内部可见,无法在其他文件中调用。
- 用途:限制函数的访问范围,防止命名冲突。
4. C++ 中 static 的使用
4.1 类静态成员变量
- 作用:类共享的变量,不属于某个对象实例。
- 访问方式:通过类名或对象实例访问。
- 存储期:静态存储期。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | #include <iostream>using namespace std;
 
 class MyClass {
 public:
 static int count;
 MyClass() { count++; }
 };
 
 int MyClass::count = 0;
 
 int main() {
 MyClass a;
 MyClass b;
 cout << "Count: " << MyClass::count << endl;
 return 0;
 }
 
 | 
4.2 类静态成员函数
- 作用:静态函数只能访问静态成员变量,不能访问非静态成员。
- 调用方式:通过类名或对象调用。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | class MyClass {public:
 static void printCount() {
 cout << "Count: " << count << endl;
 }
 static int count;
 };
 
 int MyClass::count = 0;
 
 int main() {
 MyClass::count = 10;
 MyClass::printCount();
 return 0;
 }
 
 | 
4.3 匿名命名空间替代 static(C++ 特有)
在 C++ 中,static 修饰全局函数和变量可以被匿名命名空间替代:
| 12
 3
 4
 
 | namespace {int counter = 0;
 void helper() {}
 }
 
 | 
匿名命名空间是 C++ 推荐的做法,比 static 更语义化。
5. 总结
| 使用场景 | 生命周期 | 作用域 | 特点 | 
| 全局变量 static | 程序运行期 | 文件内部 | 限制文件可见性 | 
| 局部变量 static | 程序运行期 | 函数内部 | 保留函数调用间的值 | 
| 函数 static | 程序运行期 | 文件内部 | 文件内可见,不被其他文件引用 | 
| 类静态成员变量 | 程序运行期 | 类作用域 | 所有对象共享 | 
| 类静态成员函数 | 程序运行期 | 类作用域 | 仅能访问静态成员 |