似乎是一个公认的事实,如果你用C ++这样的语言实例化一个对象,如果在编译时已知对象的大小,它只适用于堆栈放置(而不是堆分配)。例如,固定大小的数组可以放在堆栈上,但是向量的元素将放在堆上,因为在编译期间最终大小是未知的。
为什么会这样?为什么不能在运行时通过移动堆栈指针来动态分配堆栈空间?
编辑:为了澄清,这里有一个例子:在函数中间,你计算一个非常数整数。如果要创建此大小的数组,则必须在堆上完成分配,因为在编译时不知道数组的大小。但是为什么你不能在创建数组时将数组放在堆栈顶部?
答案 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已经做了所谓的“堆省略”,以便在适用时进行这些优化。