局部变量在进入其所在代码块时创建,离开时销毁;函数参数、循环/条件语句内变量均遵循此规则,static修饰可延长生命周期至程序运行期。

局部变量什么时候开始存在、什么时候消失
局部变量的生命期完全绑定在它所在的代码块执行过程里。函数调用时进入作用域,函数返回前就销毁;if 或 for 里的变量,只在对应大括号内有效。{ int x = 42; } 这行之后,x 就彻底不可见了,连名字都不存在。
常见错误现象:return &x; 返回局部变量地址,运行时可能得到垃圾值或崩溃;或者在循环里反复定义同名变量,误以为是“复用”,其实是每次新建一个独立变量。
- 函数参数也是局部变量,传值时拷贝一份,修改不影响调用方
- 用
static修饰局部变量(如static int counter = 0;),它仍属局部作用域(外部不可见),但生命周期延长到整个程序运行期 - lambda 表达式捕获的变量,若用
[=]是值捕获,捕获的是当时副本;用[&]是引用捕获,需确保被引用变量的生命周期长于 lambda 本身
全局变量和 extern 怎么跨文件共享
全局变量定义在所有函数外,具有文件作用域,默认有外部链接(extern),能被其他编译单元访问。但直接在头文件里写 int g_val = 10; 会导致多个 .cpp 包含后重复定义,链接时报错 multiple definition of 'g_val'。
正确做法分三步:
立即学习“C++免费学习笔记(深入)”;
- 头文件(
common.h)中只声明:extern int g_val; - 一个源文件(
global.cpp)中定义:int g_val = 10; - 其他源文件包含头文件后,就能读写
g_val—— 编译器靠extern知道这变量在别处定义
注意:不加 extern 的全局变量如果出现在多个 .cpp 里,每个都会生成一份定义,链接失败;加了 static 的全局变量(如 static int g_local = 5;)则只有内部链接,仅本文件可见。
namespace 怎么解决名字冲突又不污染全局作用域
全局作用域很脆弱,两个库都定义 class Logger 就直接冲突。namespace 不是语法糖,是强制隔离名字查找路径的机制。它不分配内存、不产生运行时代价,纯编译期行为。
常见误区:把 using namespace std; 写在头文件里 —— 它会把整个 std 名字“泼”进包含该头的所有源文件,极易引发隐式重定义或模板推导歧义。
- 推荐写法:在 .cpp 文件里按需引入,比如
using std::vector;或using namespace std::literals; - 嵌套命名空间(C++17 起支持
namespace A::B::C { ... })比层层大括号更清晰 - 匿名命名空间(
namespace { int helper(); })等价于static全局函数/变量,作用域限于当前翻译单元
类成员变量的作用域边界在哪
类定义内部声明的变量属于类作用域,不是全局也不是局部。它们不能在类体里初始化(除非是 static constexpr),也不能直接用 sizeof 测未完成类型大小。真正分配内存是在对象实例化时(栈、堆或静态存储区),跟声明位置无关。
容易踩的坑:this->x 和 x 在成员函数里等价,但若局部变量也叫 x,就近原则会先找到局部版 —— 此时必须显式写 this->x 才能访问成员。
- 静态成员变量(
static int count;)属于类而非对象,必须在类外定义一次(int MyClass::count = 0;),否则链接时报undefined reference - const 成员变量必须在构造函数初始化列表里赋值,不能在构造函数体内用
= - mutable 成员允许在
const成员函数里修改,常用于缓存或调试计数器
作用域规则本身不难,难的是它和链接属性(extern/static)、存储期(自动/静态/动态)、访问控制(public/private)三者交织。漏掉任意一环,编译器报错信息可能指向完全无关的行号。










