为什么对象';在编译时需要知道的内存配置文件是否用于堆栈放置? 似乎是一个公认的事实,如果你用C++语言实例化一个对象,那么如果在编译时知道对象的大小,它只适合堆栈放置(而不是堆分配)。例如,固定大小的数组可以放在堆栈上,但向量的元素将放在堆上,因为编译期间最终大小未知

为什么对象';在编译时需要知道的内存配置文件是否用于堆栈放置? 似乎是一个公认的事实,如果你用C++语言实例化一个对象,那么如果在编译时知道对象的大小,它只适合堆栈放置(而不是堆分配)。例如,固定大小的数组可以放在堆栈上,但向量的元素将放在堆上,因为编译期间最终大小未知,c++,compiler-optimization,low-level,C++,Compiler Optimization,Low Level,为什么会这样?为什么不能在运行时通过移动堆栈指针动态分配堆栈空间 编辑:为了说明,这里有一个例子:在函数的中间,计算一个非const整数。如果要创建此大小的数组,则必须在堆上进行分配,因为在编译时不知道数组的大小。但是为什么在创建数组时不能将其放在堆栈的顶部呢?请考虑以下代码: void extend(std::vector<int>& v, int val) { int w = abs(val); v.push(w) } std::vector<in

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

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

请考虑以下代码:

void extend(std::vector<int>& v, int val) {
    int w = abs(val);
    v.push(w)
}

std::vector<int> v(10);
extend(v, 3);
void扩展(标准::向量&v,int-val){
int w=绝对值(val);
v、 推力(w)
}
std::向量v(10);
扩展(v,3);

如果
v
的内容在堆栈上,它将不会是连续的,因为在v[9]和新推送的v[10]之间还有其他内容。更糟糕的是,如果强制执行该操作,那么v[10]几乎肯定会覆盖某些内容。

对于gcc,可以使用函数
alloca()
,对于Microsoft编译器,可以使用函数
\u alloca()
\u 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
}
void allocatesArray(int i)
{
char*ray=重新解释(alloca(i));
//已分配内存的“i”字节,返回void*
射线[0]=“a”;
//已释放空间,指针无效
}

请注意,这不是一个很好的做法,因为在堆栈溢出的情况下,行为未定义。

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


如果您只是想将此作为一种可能的优化方法,那么clang已经在适当的时候使用了所谓的“堆省略”来进行此类优化。

任意移动堆栈指针是不安全的,因为它主要用作“调用堆栈”,仅供参考。C++标准不使用堆栈或堆。这是一个仅在谈论特定实现时使用的术语。编译器可以自由地为自动对象使用非堆栈内存。他们为什么选择自动对象使用堆栈内存,这超出了我的专业知识。调用堆栈是一个仅从一端增长/收缩的连续内存,所以如何在其中放置任何非固定大小的结构?这并不意味着这在理论上是不可能的,但出于性能方面的原因,您不想这样做。您是否在问为什么动态对象(如vector)不能进入堆栈,或者为什么像
std::array
(其占用空间在分配后不会改变)这样的对象不能进入堆栈?(后者可以通过代码> > AlLoa在堆栈上,如果编译器支持它)换句话说:为什么C++不接受VLA,像C?我认为添加搜索词可以更容易地找到相关信息。我认为OP提出的是相反的问题。如果定义
int数组[10]
作为一个函数变量,为什么不能从堆栈以外的位置分配
数组的内存呢?我同意,向量将不再连续存储,因为v[10]将位于堆栈的顶部,在w之后。这对我来说似乎不是很成问题,忽略了向量规范说它将被连续存储。但总的来说,我仍然不明白为什么不能在堆栈上进行动态分配。也许要问的问题是:您希望通过想象中的功能获得什么好处?@RSahu如果这样,C99(而不是C++)中有VLA,某些实现在堆栈上分配动态数组,所以答案是肯定的。也许我遗漏了什么,但似乎“最顶层的情况”是默认情况。例如,控制流位于一个函数的中间,它只是计算了一个在编译时未知的变量,然后需要创建一个这样大小的数组。为什么它不能把这个数组放在堆栈的顶部,即使它的大小在编译时是未知的?为什么它不能呢?可以肯定的是,GCC已经有了一个针对可变大小堆栈数组的扩展。也许这是编译器编写人员需要进一步优化的地方。