use*_*689 10 c c++ templates visual-c++ c++11
这似乎是一个初学者的问题,但我对编译器通常创建变量维数组的方式感兴趣,就像在下面的程序中一样.
#include<iostream>
int main(){
int n;
std::cin>>n;
int a[n];
}
Run Code Online (Sandbox Code Playgroud)
根据我的学习,在C中,所有初始化值都必须是常量,这样编译器就知道要在函数内保留多少内存,通常是通过减去堆栈指针来容纳数组所包含的元素数.
这对我来说很有意义.但是,我不太明白编译器如何处理上述程序,因为它似乎与G ++(MinGW)一起工作,但是在C,Microsoft的C++编译器中失败了.我怀疑GCC通过非标准扩展在堆上分配内存,但我不确定.
此外,微软的编译器并不因标准兼容而闻名,所以如果它对待上述程序的方式实际上可能出错,我也不会感到惊讶.
bdo*_*lan 12
在C标准的C99版本中,允许使用可变长度数组.但是,它们不允许在任何版本的C++中使用; 你正在看一个G ++扩展.请注意,Microsoft的C编译器不完全支持C99; 由于G ++支持C99,因此很容易将VLA支持应用于C++作为扩展.
至于编译器通常如何实现VLA,它是相同的alloca()(除了它必须保持大小sizeof) - 编译器保存原始堆栈指针,然后通过计算它需要的许多字节将其调低.缺点是函数入口和出口有点复杂,因为编译器需要存储重置堆栈指针的位置,而不是仅仅通过固定常量进行调整.
通过运行时值"运行时减去堆栈指针"绝对没有问题.这就是编译器通常如何实现可变长度数组.当实际的数组大小已知时,它们在运行时"减去堆栈指针".这里的所有都是它的.(没有必要在堆上分配内存,我不知道是什么让你在GCC中怀疑这个.).
在VLA成为该语言的一部分之前很久就可以使用这种功能.[非标准]功能alloca正是如此.唯一的区别是alloca当函数退出时,分配的内存会自动解除分配,而本地的VLA必须遵守基于块的标准生存期规则.后者根本不是问题,因为嵌套以类似堆栈的方式嵌套.
换句话说,对于运行时值n的声明
int a[n];
Run Code Online (Sandbox Code Playgroud)
基本上被翻译成类似的东西
int *a = alloca(n * sizeof *a);
Run Code Online (Sandbox Code Playgroud)
加上一些额外的家庭数据来支持sizeof等功能(当然,还可以在封闭块的末尾自动恢复原始堆栈指针值).
| 归档时间: |
|
| 查看次数: |
1995 次 |
| 最近记录: |