数组在内存中是连续存储的,这是它能实现o(1)随机访问的根本原因;其地址计算为base_address + i * sizeof(t),静态数组依定义位置落于栈、全局区或堆,二维数组实为一维连续块,越界访问行为未定义。

数组在内存中是连续存储的,这是它能实现 O(1) 随机访问的根本原因。只要知道首地址和元素大小,arr[i] 就能直接算出物理地址:base_address + i * sizeof(T)。
静态数组的内存位置由定义方式决定
编译器不会把所有数组塞进同一个地方,它的落点完全看你怎么写:
- 函数内定义的
int arr[100]→ 栈上分配;栈空间小(通常 1–8MB),过大的数组(比如int big[1000000])会触发stack overflow - 全局或
static int arr[100]→ 全局/静态区;生命周期贯穿整个程序,初始化为 0(未显式赋值的部分) -
int* p = new int[100]→ 堆上分配;大小运行时确定,需手动delete[] p,否则内存泄漏
二维数组不是“表格”,而是一维连续块
C++ 没有真正的二维结构,int a[3][4] 在内存里就是 12 个 int 顺次排开: a[0][0], a[0][1], a[0][2], a[0][3], a[1][0], ..., a[2][3]。所谓“行优先”只是你解读数据的方式,底层没有分隔符或元信息。
这意味着:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
&a[1][0]和&a[0][4]是同一地址(假设sizeof(int) == 4) -
a[1]的类型是int[4],它本身是一个左值,但退化为指针时变成int*,指向a[1][0] - 用
int**去接a是错的——a不是指向指针的指针,而是一个块的起始地址
越界访问不会报错,但后果不可控
C++ 标准不强制检查下标,arr[100] 对 int arr[5] 来说语法合法,运行时行为未定义:
- 可能读到栈上相邻变量的垃圾值(比如把
int x和int arr[5]紧挨着声明,arr[5]实际读到了x) - 可能触发段错误(访问了未映射的页)
- 可能悄无声息地改写其他变量,导致后期逻辑错乱,极难调试
别依赖编译器警告或 ASan(AddressSanitizer)来兜底——它们只覆盖部分场景。真要安全,得用 std::array 或 std::vector 配合 .at(),或者自己做边界断言。
真正容易被忽略的是:数组名不是指针变量,而是常量地址;它不占对象存储空间,也不可取地址(&arr 合法,但那是整个数组对象的地址,类型是 int(*)[5],不是 int**)。这点混淆会导致大量指针运算错误。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










