可以。

变量作为数组的长度,以及访问超过长度的数组下标:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

void func(int num) {
int array[num]; // num > 0
cout << "num " << num << endl;
cout << "sizeof array " << sizeof(array) << endl;
array[0] = 20;
cout << "array[0] " << array[0] << endl;

array[10] = 2000;
cout << "array[10] " << array[10] << endl;
}

int main() {
func(6);
return 0;
}

输出:

1
2
3
4
5
6
7
8
num 6
sizeof array 24
array[0] 20
array[10] 2000

--------------------------------
Process exited after 0.01307 seconds with return value 0
请按任意键继续. . .

可以看到数组是可以是变量的,而且访问超过长度的数组下标也是可以的。

那么为什么都说数组要用常量初始化呢?

结论:尽管C++目前支持变量长度的数组,但是不建议使用,因为数组使用的是栈内存,栈内存是有大小限制的,一般是8192字节,既然长度是变量,那就可能是任何值,就有可能超过8192,这样就会stack overflow,所以动态内存最好使用堆内存。

操作超过数组长度的内存会发生什么?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
using namespace std;

void func() {
int array[10];
array[3] = 1;
array[40] = 3;
cout << "sizeof array " << sizeof(array) << endl;
cout << "array[3] " << array[3] << endl;
cout << "array[40] " << array[40] << endl;
}

int main() {
int a[200];
for (int i = 0; i < 200; ++i) {
a[i] = 100;
}
for (int i = 0; i < 200; ++i) {
cout << a[i] << " ";
}
cout << endl << "=====================" << endl;

func();
cout << "=====================" << endl;
for (int i = 0; i < 200; ++i) {
cout << a[i] << " ";
}
cout << endl << "=====================" << endl;
return 0;
}

输出:

1
2
3
4
5
6
7
8
9
10
11
12
100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
=====================
sizeof array 40
array[3] 1
array[40] 3
=====================
100 100 100 100 100 100 100 100 100 100 100 100 3 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
=====================

--------------------------------
Process exited after 0.07259 seconds with return value 0
请按任意键继续. . .

看输出,可以看到数组a的一个值被改成了3,因为数组使用的是栈内存,栈帧内存是向下增长的(地址逐渐减小),代码中操作了超过数组长度的内存地址,就影响到了之前栈帧的内存数据,导致之前栈内存数据出现错误,可能就会引发bug。

总结:

C++中数组长度可以是变量,但是不建议使用,因为数组使用的是栈内存,变量可以是个比较大的数,这样会导致stack overflow,建议使用堆内存。

操作超过数组长度的内存可以编译通过且表面上看不出来问题,但是会导致栈内存出现脏写,最终可能会引发难以排查的bug,建议数组使用std::array,操作超过长度的下标会抛异常有利于开发者及时发现错误。

参考链接:

https://mp.weixin.qq.com/s/rR6YhNdZDLQ2TADfDzWP3Q