# C/C++ static 的用法详解
在 C/C++中,`static` 是一个多用途的关键字,用法因语境(全局、局部、类/结构体、函数等)而异,核心作用是**控制变量/函数的生命周期、可见性或存储方式**。
## 在C 语言中的 `static` 用
### 1. 文件作用域:静态全局变量
– **定义**:在全局变量前加 `static`,其作用域会被限制在当前编译单元(`.c` 文件),在其他文件中不可见。
– **生命周期**:与程序同生共死(生命周期相同)。
– **特性**:
– 避免全局变量命名冲突(其他文件可定义同名变量,互不干扰)。
– 仅在当前文件内可访问,实现“文件内私有”。
“`c
// file1.c
// 静态全局变量,仅 file1.c 可见。
static int g_val = 10;
// file2.c
// 与 file1.c 的 g_val 不冲突,各自独立。
int g_val = 20;
“`
### 2. 函数作用域:静态局部变量
– **定义**:在函数内部定义的变量前加 `static`,作用域仍限于函数内部。
– **生命周期**:函数首次被调用时初始化此静态变量且仅初始化这一次,但可以被修改(非const变量),其生命周期延长至整个程序结束。
– **特性**:
– 对于函数内定义的静态局部变量不会因为函数的退出而销毁且可以保持其最新状态到程序结束。
– 限定此类静态变量的作用域仅在定义它的函数内部。
“`c
#include
int count()
{
// 静态局部变量,仅初始化一次
static int cnt = 0;
cnt++;
return cnt;
}
int main()
{
// 输出 1
printf(“%d “, count());
// 输出 2
printf(“%d “, count());
// 输出 3
printf(“%d “, count());
return 0;
}
“`
### 3. 文件作用域:静态函数
– **定义**:在函数前加 `static`,作用域限制在当前编译单元(`.c` 文件),其他文件无法调用。
– **特性**:
– 可以避免函数命名冲突(在其他文件可定义同名函数)。
– 将函数的作用域限定在当前编译单元,可以隐藏内部实现,实现私有化的效果。
“`c
// file1.c
static void helper()
{
// 静态函数,仅 file1.c 内可调用
printf(“Helper function\n”);
}
void public_func() {
helper(); // 合法:同一文件内可调用
}
// file2.c
// 声明外部函数
void public_func();
// 错误:无法声明其他文件的静态函数
// void helper();
int main()
{
// 合法:调用 public_func
public_func();
// 错误:无法访问 file1.c 的静态函数
// helper();
return 0;
}
“`
## C++ 中扩展的 `static` 用法(兼容 C,新增类相关用法)
### 1. 类作用域:静态成员变量
– **定义**:在类的成员变量前加 `static`,属于整个类而非某个对象,此类的所有对象共享此静态成员。
– **特性**:
– 必须在类外初始化(类内仅声明),初始化时不加 `static`。
– 可通过 `类名::变量名` 或 `对象.变量名` 访问(推荐前者)。
– 生命周期与程序一致,不依赖对象创建。
“`cpp
#include
class MyClass
{
public:
static int _val; // 类内声明静态成员变量
};
// 类外初始化(必须!否则链接错误)
int MyClass::_val = 100;
int main()
{
MyClass obj1, obj2;
obj1._val = 200;
// 输出 200(所有对象共享)
std::cout << obj2._val << std::endl;
// 输出 200(推荐用法)
std::cout << MyClass::_val << std::endl;
return 0;
}
```
### 2. 类作用域:静态成员函数
- **定义**:在类的成员函数前加 `static`,属于类本身,不依赖对象即可调用。
- **特性**:
- 无 `this` 指针,无法访问非静态成员(变量/函数),只能访问静态成员。
- 可通过 `类名::函数名` 或 `对象.函数名` 调用(推荐前者)。
- 不能被 `virtual` 修饰(无多态特性)。
```cpp
#include
class MathUtil
{
public:
static int Add(int a, int b)
{
// 静态成员函数
return a + b;
}
// 静态成员变量
static double _pi;
};
// 初始化静态成员变量(部分常量可以在类内部直接初始化)
double MathUtil::_pi = 3.14;
int main()
{
// 无需创建对象,直接通过类名调用
// 输出 5
std::cout << MathUtil::Add(2, 3) << std::endl;
return 0;
}
```
### 3.(类/结构体)成员函数作用域:局部静态变量被此(类/结构体)的所有对象共享
- 在 C++ 中,类的静态成员函数或非静态成员函数内的静态局部变量,与普通函数的静态局部变量特性一致,仅初始化一次且生命周期与程序一致。
```cpp
class Counter
{
public:
int GetCount()
{
// 静态局部变量,所有对象共享
// 此处要特别注意,容易因为并行计算踩坑。
static int cnt = 0;
cnt++;
return cnt;
}
};
int main() {
Counter c1, c2;
// 输出 1 2
std::cout << c1.GetCount() << " " << c2.GetCount() << std::endl;
return 0;
}
```
### 4. 模版类:静态成员
类模板的静态成员变量/函数,会为每个模板实例化类型生成独立的副本(而非所有实例共享)。
- 示例:
```cpp
#include
template
class TempClass
{
public:
// 静态模板成员变量
static int _val;
};
// 为每个模板类型初始化
template
int TempClass
int main()
{
TempClass
TempClass
// 输出 10 20
std::cout << TempClass

