c++数组长度必须为编译期常量,不支持变长数组;合法来源仅字面量、constexpr变量、模板参数;运行时大小应使用std::vector或动态内存。

数组长度必须是编译期常量,不能用变量
你写 int n = 5; int arr[n]; 会报错:error: variable length array declaration not allowed in C++。这不是“写法不规范”,而是标准禁止——C++ 不支持变长数组(VLAs)。哪怕 GCC/Clang 在某些模式下允许,也是非标准扩展,换编译器或加严格选项就崩。
合法的长度来源只有三种:
- 字面量:
int arr[10]; -
constexpr变量:constexpr int N = 10; int arr[N]; - 模板参数:
template<int n> void f() { int a[N]; }</int>
运行时才知道大小?别硬扛,直接上 std::vector<int></int> 或者 new int[n](记得配对 delete[])。
初始化方式选哪一种,取决于你要不要省心和兼容
常见写法有四类,行为略有差异:
-
int arr[5] = {1, 2, 3};:部分初始化,后两个元素自动为0 -
int arr[] = {1, 2, 3};:省略长度,编译器推导为3;但仅限定义处可用,传参时退化为指针 -
int arr[5]{};:空花括号,全部元素零初始化(安全,推荐) -
int arr[5]{1, 2};:C++11 直接列表初始化,更严格——如果初值多于 5 个,编译失败;少于则补零
注意:char s[] = "abc"; 是特例,长度自动算成 4(含 '\0');但 char s[3] = "abc"; 是越界,编译器通常报 initializer-string for char array is too long。
传参时数组名会丢长度,引用声明才能保住
函数形参写 void f(int arr[5]) 或 void f(int arr[]) 或 void f(int* arr),三者完全等价,sizeof(arr) 在函数内永远是 8(指针大小),不是数组总字节。
想让函数知道长度,必须用引用:
-
void f(int (&a)[5]):绑定到长度为 5 的数组,sizeof(a)正确,且无法传入其他长度数组 -
void f(std::array<int>& a)</int>:更现代,支持.size()、.at()等成员
别在头文件里直接写 int arr[10]; ——每个 .cpp 包含它都会生成一份副本,链接时报 multiple definition of 'arr'。正确做法是头文件中写 extern int arr[10];,一个 .cpp 里定义 int arr[10];,或者用 inline constexpr std::array<int> arr = {1,2,3};</int>(C++17 起)。
越界访问不报错,但后果你担不起
int arr[3]; arr[5] = 42; 编译通过,运行可能不崩溃,也可能改掉隔壁变量、触发段错误、或者看似正常——这是未定义行为(UB),不是“运气好”。调试阶段务必加 -fsanitize=address,它会在越界时立刻报错并指出位置。
生产代码中,除非性能极端敏感且确认逻辑绝对安全,否则优先用 std::array 的 at() 方法(抛异常)或 std::vector,而不是裸 []。循环遍历时,下标上限别硬写数字,也别依赖传进来的数组还带着原始长度信息——它早就退化了。
真正容易被忽略的点:静态存储期数组(static int a[3]; 或全局)会自动零初始化;而函数内局部数组 int a[3]; 不初始化就是垃圾值,别误以为是 0。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











