C ++中的可变长度数组开销?

看看这个问题:为什么C / C ++编译器在编译时需要知道数组的大小?它来到我身边,编译器实现者应该有一些时间来了解它(它是C99标准的一部分,那是10年前)并提供有效的实现。 然而,(从答案中)似乎仍然被认为是昂贵的。 这让我感到惊讶。 当然,我理解静态偏移在性能方面比动态偏移要好得多,并且不像一个建议我实际上不会让编译器执行数组的堆分配,因为这可能会花费更多[这没有被测量;)] 但我仍然对所谓的成本感到惊讶: 如果一个函数中没有VLA,那么就我所知,不会有任何代价。 如果有一个单独的VLA,那么可以在所有变量之前或之后放置它,因此获得大部分堆栈帧的静态偏移量(或者在我看来,但是我对堆栈管理并不精通) ) 当然,问题出现在多个VLA上,我想知道是否有专用的VLA堆栈可行。这意味着VLA将由计数和指针(因此已知大小)表示,并且在辅助堆栈中采用的实际内存仅用于此目的(因此也是堆栈)。 [改述] 如何在gcc / VC ++中实现VLA? 成本真的令人印象深刻吗? [结束改写] 在我看来,它只能比使用
vector
更好,即使是现有的实现,因为你不会产生动态分配的代价(以不可调整大小为代价)。 编辑: 这里有一个部分响应,但是将VLA与传统阵列进行比较似乎是不公平的。如果我们事先知道尺寸,那么我们就不需要VLA了。在同一个问题中,AndreyT给出了一些关于实现的指示,但它并不像我想的那样精确。     
已邀请:
  如何在gcc / VC ++中实现VLA? AFAIK VC ++不实现VLA。它是一个C ++编译器,它只支持C89(没有VLA,没有限制)。我不知道gcc如何实现VLA,但最快的方法是将指针存储到VLA及其大小在堆栈帧的静态部分。通过这种方式,您可以访问其中一个具有常量大小数组的VLA(如果堆栈像x86一样向下扩展,则是最后一个VLA(取消引用[堆栈指针+索引*元素大小+上次临时推送的大小]),和第一个VLA,如果它向上增长(取消引用[stackframe指针+偏离stackframe + index *元素大小]))。所有其他的VLA都需要一个间接来从堆栈的静态部分获取它们的基址。 [编辑:同样在使用VLA时,编译器不能省略堆栈帧基指针,否则这是冗余的,因为堆栈指针的所有偏移都可以在编译期间计算。所以你少了一个免费注册。 —结束编辑]   成本真的令人印象深刻吗? 并不是的。此外,如果您不使用它,您不需要付费。 [编辑:可能更正确的答案是:与什么相比?与堆分配的向量相比,访问时间将相同,但分配和释放将更快。 —结束编辑]     
如果它是用VC ++实现的,我会假设编译器团队会使用一些
_alloca(size)
的变体。我认为成本相当于在堆栈上使用大于8字节对齐的变量(例如
__m128
);编译器必须将原始堆栈指针存储在某处,并且对齐堆栈需要额外的寄存器来存储未对齐的堆栈。 所以开销基本上是一个额外的间接(你必须在某处存储VLA的地址)并注册压力,因为在某处也存储了原始堆栈范围。     

要回复问题请先登录注册