全局变量可在所有函数中使用,但需定义在函数外部且满足链接要求;跨文件需extern声明,同名局部变量会遮蔽它,多线程访问需同步,初始化顺序跨编译单元未定义。

全局变量可以在所有函数里使用,只要它定义在函数外部且可见
全局变量的可见范围取决于定义位置和链接属性
全局变量必须定义在所有函数之外(即翻译单元顶层),不能包在 {} 里、不能在 main 内、也不能在类定义内部。满足这个前提后,它默认具有 external linkage,意味着:
- 在同一
.cpp文件中:所有函数(main、自定义函数、静态成员函数外的普通函数)都能直接读写 - 在其他
.cpp文件中:需用extern int g_var;声明后才能使用(注意不是extern int g_var = 0;,那会变成定义) - 若加了
static或放在匿名命名空间里(namespace { int g_local; }),则仅本文件内函数可访问,其他文件即使extern也链接失败
哪些函数“不能”直接用?——其实是作用域遮蔽或链接问题
不是函数类型限制了访问,而是以下情况会导致看似“不能用”:
- 函数内部定义了同名局部变量:
int g_counter = 100;会遮蔽全局g_counter,此时访问的是局部变量 - 跨文件未声明就使用:编译器报
undefined reference to 'g_config',本质是链接阶段找不到定义 - 头文件里误写了定义(如
int g_flag = 1;):被多个.cpp包含后触发 ODR 违规,链接时报multiple definition of 'g_flag' - 在模板函数或内联函数里使用时,若该函数被导出到其他 TU,仍需确保
g_var有 external linkage 且已定义
多线程环境下直接访问全局变量很危险
即使语法上所有函数都能读写,但并发修改会导致未定义行为:
立即学习“C++免费学习笔记(深入)”;
- 不加同步(如
std::mutex、std::atomic)时,g_counter++不是原子操作,可能丢失更新 - 不同线程对同一全局变量的读写顺序无保证,编译器和 CPU 都可能重排指令
- 静态局部变量的初始化(
static T x = init();)虽线程安全(C++11 起),但全局变量的构造函数执行顺序跨 TU 是未指定的,容易引发初始化顺序 fiasco
真正麻烦的从来不是“能不能用”,而是“谁在什么时候改了它”——尤其当函数分布在多个文件、被不同线程调用、还混着静态初始化时,全局变量的生命周期和访问边界很容易失控。


















