首先介绍静态变量特性
-
生命周期:
-
全局静态变量:在程序的整个生命周期内存在,初始化后一直保留,直到程序结束才被销毁。‘
-
局部静态变量:与局部变量不同,局部静态变量在函数或代码块的第一次执行时被初始化,并且在程序的整个生命周期内保持存在,不会在函数或代码块退出时被销毁。
void increase() { static int counter = 0; counter++; std::cout << "Counter: " << counter << std::endl; } int main() { increase(); // 输出: Counter: 1 increase(); // 输出: Counter: 2 increase(); // 输出: Counter: 3 return 0; }
-
-
作用域:
- 局部静态变量:它的作用域是局部的,只能在声明它的函数或代码块内访问。尽管它的生命周期延续到程序结束。
- 全局静态变量:它的作用域是文件内部,只有在声明它的文件内的代码才能访问,其他文件无法访问。注意:不可以使用extern来试图在其它文件访问全局静态变量!
-
内存分配
- 存储位置:静态变量存储在静态存储区中。这些数据在程序启动时分配,并在程序结束时释放。
- 对于局部静态变量也会被存储在静态存储区,在程序运行前,即编译时,会为它在静态存储区分配空间,但不进行初始化。直到在第一次执行到其所在的函数并且首次使用该变量时才进行初始化。如果没有进行显式初始化,默认值为0.
C++11 之后保证静态变量线程安全
在 C++11 及之后的标准中,局部静态变量的初始化是线程安全的,这意味着即使多个线程同时访问同一个静态局部变量,它也只会被初始化一次
静态变量的初始化规则
- 在多线程环境中,当一个线程首次遇到静态局部变量的定义时,它会检查该变量是否已经初始化:
- 如果已经被初始化:后续线程将直接使用该变量,而不会再次初始化它
- 如果没有:编译器会确保它在当前线程中完成初始化,同时阻塞其他线程的访问,直到初始化完成。这确保了即使多个线程同时到达这段代码,静态变量也只会被初始化一次。
- 虽然初始化是线程安全的,但如果多个线程同时修改一个静态变量(无论是局部静态还是全局静态),通常需要同步机制来避免数据竞争。