运行时C++数组初始化问题

3
为什么我们不能在全局区域(outside main())使用非const大小初始化数组大小?
//outside main - global
int val=5;
int arr[val];

int main()
{

}

这会导致错误。

7:12: error: array bound is not an integer constant before ']' token
 In function 'int main()':

但是,如果将相同的代码移动到函数主体/正文中,则错误消失......

没有错误,可以编译正常......

int main()
{
   int val=5;
   int arr[val];
}

同样,它可以在函数体内正常工作。

void fn(int val)
{
    int arr[val];
}

int main()
{

fn(5);

}

为什么移动数组的大小只能在main函数外初始化会让人感到困惑?


1
C++不支持动态数组声明,你需要使用int* arr = new int(val) - suzuiyue
在标准 C++ 中,您不能像在 C 中那样使用可变长度数组(VLA)(虽然 G++ 作为扩展允许这样做)。即使在 C 中,在文件范围内也无法定义可变长度数组。而且,在 C 中不能初始化 VLA - 虽然您的代码没有尝试初始化 VLA,因此不清楚您是否按照通常的方式使用了标准术语“initialize”。您的函数 fn 没有对 VLA 做任何事情;编译器可能会删除该数组(尽管如果优化掉数组,则在将负值或零值传递给 val 时可能无法获得应该出现的错误)。 - Jonathan Leffler
1
只需在 c++ 中使用 std::vector 即可。 - drescherjm
@suzuiyue:你定义了一个指向单个整数的指针并初始化为val,是吗?我认为C++中相当于定义一个包含val个整数的数组应该更像是 int *arr = new int[val]; ——假设你使用了new(或者更确切地说是new[])。现代C++会避免使用所有这些符号。 - Jonathan Leffler
2个回答

4
第一个示例,在文件作用域
int val=5;
int arr[val];

int main()

在 C 和 C++ 中都是非法的。文件作用域变量必须在第一次使用之前定义(创建),并持续存在直到程序结束 - 这也意味着,一旦创建,数组大小不能更改。对于数组来说,这意味着(除其他事项外)它们的维度必须在编译时知道。将变量用作数组维度违反了静态大小需要在编译时已知的需求 - 例如,val 的值可能会在运行时(例如在 main() 中)更改,这将发生在 arr 创建之后。

第二个示例:

void fn(int val)
{
     int arr[val];
}
在C语言(1999年版)中,arr是自动存储期限的,因此合法。函数体输入时创建,函数返回时消失,这称为“可变长数组”或VLA,因为元素数量由运行时变量val的值确定。
在1999年之前的C标准中也不支持VLA。
在C++中,VLAs是非法的。然而,一些C++编译器作为非标准扩展支持这样的特性。与使用数组不同,在C++中首选使用标准容器(例如std::vector<int>),原因包括在运行时能够调整大小。

3

对于函数内的数组:

你正在依赖于GCC扩展,如果你添加-pedantic参数,你将收到以下警告:

警告:ISO C++不允许可变长度数组'arr'[-Wvla]

因此,C ++不支持可变长度数组,建议使用std::vector替代。

对于函数外的数组:

你需要在int之前添加const。是的,我知道编译器从理论上可以推断出val永远不会被改变,但由于某些原因(没有人想把它加入标准中,或者有很好的理由不这样做),你需要添加const。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接