Кажется, это общепризнанный факт, что если вы создаете экземпляр объекта на языке, подобном C ++, он имеет право на размещение в стеке (а не на выделение кучи), если размер объекта известен во время компиляции. Например, массив фиксированного размера может помещаться в стек, но элементы вектора будут помещаться в кучу, поскольку окончательный размер неизвестен во время компиляции.
Почему это так? Почему пространство стека не может быть динамически выделено во время выполнения путем перемещения указателя стека?
РЕДАКТИРОВАТЬ: Для пояснения, вот пример: в середине функции вы вычисляете неконстантное целое число. Если вы хотите создать массив этого размера, выделение должно выполняться в куче, потому что размер массива неизвестен во время компиляции. Но почему вы не можете просто поместить массив на вершину стека при его создании?
Рассмотрим этот код:
void extend(std::vector<int>& v, int val) {
int w = abs(val);
v.push(w)
}
std::vector<int> v(10);
extend(v, 3);
Если содержание v
находится в стеке, оно не будет непрерывным, так как между v [9] и вновь выдвинутым v [10] есть другие вещи. Хуже того, если операция принудительная, то v [10] почти наверняка что-то перезапишет.
Вы можете сделать это с помощью функции alloca()
для GCC, и функции _alloca()
а также _malloca()
для компиляторов Microsoft.
Это выглядит следующим образом:
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
}
Имейте в виду, что это не считается очень хорошей практикой из-за неопределенного поведения в случае переполнения стека.
То, что вы не можете сделать, если вы не находитесь на самой вершине стека, это изменение размера, так как вы не можете перемещать весь стек вокруг. Если у вас есть какая-то структура данных, которая может каким-либо образом изменить размер, вы не можете использовать ее при любом вызове функции из вашей текущей области с неконстантным контекстом.
Если вы просто думаете об этом как о возможном способе оптимизации вещей, clang уже делает так называемое «решение для кучи», чтобы выполнить такие виды оптимизации, когда это применимо.