数组生命周期由声明位置和存储期决定,与是否为数组无关:全局数组静态存储、函数内普通数组自动存储、static局部数组静态存储但作用域受限、new分配数组需手动管理。

数组的生命周期完全由其声明位置和存储期决定,跟“是不是数组”无关——它只是变量的一种类型。
全局作用域定义的数组:程序启动即存在,结束才释放
在所有函数外部定义的数组(如 int arr[10];),属于静态存储期。它在程序加载时就分配在 .data 段(已初始化)或 .bss 段(未初始化),生命周期覆盖整个程序运行过程。
- 即使没被任何函数访问,内存也一直占用
- 多文件项目中,若需在其他源文件使用,必须用
extern int arr[10];声明,不能重复定义 - 初始化列表只执行一次:
int arr[3] = {1};→{1, 0, 0},且该初始化发生在main()之前
函数内定义的普通数组:进块生,出块死
写在函数体或任意 {} 块内的数组(如 void f() { int buf[100]; }),是自动存储期变量,本质就是栈上连续分配的一段内存。
- 每次进入作用域才分配(包括递归调用),离开时立即释放——不是“清零”,而是栈指针回退,内存不再受保护
- 未显式初始化时内容是随机值(
int local[5];中元素值不可预测) - 数组名
local是常量地址,但整个对象生命周期仅限当前块;返回它的指针会导致悬空指针:return local;❌
函数内 static 数组:只初始化一次,但作用域仍受限
用 static 修饰的局部数组(如 static char cache[256];),生命周期升级为静态存储期,但作用域仍是函数内部。
立即学习“C++免费学习笔记(深入)”;
- 首次执行到该行时初始化(之后跳过),内存位于静态区,不随函数退出而销毁
- 适合做缓存、计数器等需要跨多次调用保留状态的场景
- 注意:多线程并发调用时,多个线程共享同一份内存,需自行加锁,
static不提供线程安全 - 不能在头文件里定义(否则每个包含它的 .cpp 都会生成一份副本,链接时报重定义)
new 动态分配的数组:手动控制生死,极易泄漏
用 new[] 分配的数组(如 int* p = new int[20];)生命周期由程序员显式管理,存储在堆上。
- 必须配对使用
delete[] p;,用delete p;会引发未定义行为 - 忘记
delete[]→ 内存泄漏;重复delete[]→ 程序崩溃 - 异常可能绕过
delete[]语句,推荐改用std::vector或std::unique_ptr<int></int> - 数组大小可以是运行时变量:
int n = get_size(); int* dyn = new int[n];,但普通局部数组不行
真正容易被忽略的是:数组本身没有特殊生命周期规则,它完全服从所声明位置的存储期约定。混淆作用域(能不能写名字)和生命周期(内存还在不在),是悬空指针和未定义行为最常见的根源。


















