全局变量需在函数外定义,默认外部链接,可用static或inline限制可见性;局部变量作用域内构造析构,禁返地址/引用;static局部变量仅初化一次,存于静态存储区。

全局变量必须在函数外部定义,且注意链接性
全局变量的作用域从定义处开始到整个翻译单元末尾,但默认具有外部链接(external linkage),意味着其他文件也能通过 extern 引用它。如果只想在当前文件用,得加 static 或 inline(C++17 起)修饰:
-
int global_a = 42;—— 其他.cpp文件可用extern int global_a;访问,但重复定义会链接错误 -
static int global_b = 10;—— 仅本文件可见,避免命名冲突 -
inline int global_c = 5;—— C++17 起支持,允许多个定义(如头文件中),不会链接冲突
别在头文件里写非 inline/static 的初始化定义,否则包含多次就报 multiple definition 错误。
局部变量在函数/语句块内声明,生命周期受作用域限制
局部变量在进入作用域时构造,离开时析构(对类类型),内存通常在栈上分配。常见误区是返回局部变量的地址或引用:
-
int* bad() { int x = 100; return &x; }——x离开函数即销毁,返回指针悬空 -
const std::string& also_bad() { std::string s = "hello"; return s; }—— 同样悬空,即使加const也不延长生命周期 - 需要返回对象内容时,直接返回值:
std::string good() { return "hello"; }—— C++17 后 guaranteed copy elision,无额外开销
循环内声明局部变量(如 for (int i = 0; ...))每次迭代都会重新构造和析构,对轻量类型无妨,但对重对象要考虑性能。
立即学习“C++免费学习笔记(深入)”;
static 局部变量:只初始化一次,生存期贯穿整个程序运行
static 修饰的局部变量保留在静态存储区,首次执行到声明时初始化,之后调用跳过初始化,值保持上次结束时的状态:
void counter() {
static int count = 0; // 只在第一次调用时初始化为 0
++count;
std::cout << count << "\n";
}
// 第一次调用输出 1,第二次 2,依此类推
注意:static int count = some_func(); 中 some_func() 也只在首次进入作用域时调用一次;多线程环境下需手动同步,因为初始化本身是线程安全的(C++11 起),但后续读写不是。
区分声明与定义,避免未定义行为
声明告诉编译器变量名和类型,定义才分配内存。全局变量容易混淆这点:
-
extern int g;—— 声明,不分配空间,需在某处有定义 -
int g = 42;—— 定义(带初始化),分配空间 -
int g;—— 这是“暂定定义”(tentative definition),在 C++ 中不合法;C++ 要求有且仅有一个定义,所以这种写法在 C++ 中属于定义(且初始化为 0),但极易引发 ODR 违反
最安全的做法:头文件里只放 extern 声明(或 inline 定义),源文件里放唯一定义。局部变量不存在声明/定义分离问题,所有都是定义。


















