为什么在编译时需要知道对象的内存配置文件以进行堆栈放置?

时间:2018-05-03 05:14:14

标签: c++ compiler-optimization low-level

似乎是一个公认的事实,如果你用C ++这样的语言实例化一个对象,如果在编译时已知对象的大小,它只适用于堆栈放置(而不是堆分配)。例如,固定大小的数组可以放在堆栈上,但是向量的元素将放在堆上,因为在编译期间最终大小是未知的。

为什么会这样?为什么不能在运行时通过移动堆栈指针来动态分配堆栈空间?

编辑:为了澄清,这里有一个例子:在函数中间,你计算一个非常数整数。如果要创建此大小的数组,则必须在堆上完成分配,因为在编译时不知道数组的大小。但是为什么你不能在创建数组时将数组放在堆栈顶部?

3 个答案:

答案 0 :(得分:2)

考虑以下代码:

0

如果void extend(std::vector<int>& v, int val) { int w = abs(val); v.push(w) } std::vector<int> v(10); extend(v, 3); 的内容在堆栈中,它将不会连续,因为v [9]和新推送的v [10]之间存在其他内容。更糟糕的是,如果操作是强制的,那么v [10]几乎肯定会覆盖某些东西。

答案 1 :(得分:1)

您可以使用gcc的alloca()函数和Microsoft编译器的函数_alloca()_malloca()

这看起来如下:

void allocatesArray(int i)
{
    char *ray = reinterpret_cast<char*>(alloca(i));
    // 'i' bytes of memory allocated, returns void * 

    ray[0] = 'a';
    // space freed, pointer invalidated
}

请注意,由于堆栈溢出时的未定义行为,因此不会将其视为一种非常好的做法。

答案 2 :(得分:0)

除非你处于最顶层,否则你不能做的就是调整大小,因为你无法移动整个堆栈。如果您有一些可能以任何方式改变大小的数据结构,则不能在当前作用域中使用非const上下文的任何函数调用中使用它。

如果您只是将此视为优化事物的一种可能方式,那么clang已经做了所谓的“堆省略”,以便在适用时进行这些优化。