Я действительно не понимаю, почему у меня не может быть массив переменных размера в стеке, поэтому что-то вроде
foo(int n) {
int a[n];
}
Как я понимаю, стек (-сегмент) части сегмента данных и, следовательно, не имеет "постоянного размера".
Я действительно не понимаю, почему у меня не может быть массив переменных размера в стеке, поэтому что-то вроде
foo(int n) {
int a[n];
}
Как я понимаю, стек (-сегмент) части сегмента данных и, следовательно, не имеет "постоянного размера".
Массивы переменной длины (VLA) не разрешены на С++ в соответствии со стандартом С++.
Многие компиляторы, включая gcc, поддерживают их как расширение компилятора, но важно отметить, что любой код, который использует такое расширение, не переносится.
С++ предоставляет std::vector для реализации аналогичной функции VLA.
Было предложено , чтобы ввести Variable Length Arrays в С++ 11, но в итоге было отброшено, потому что для этого потребовались бы большие изменения к системе типов в С++. Преимущество создания небольших массивов в стеке без потери пространства или вызывающих конструкторов для неиспользуемых элементов считалось недостаточно значительным для больших изменений в системе типа С++.
VLA, как описано в N3639, была принята на Бристольской встрече и станет частью С++ 14, а также библиотекой-счетчиком "dynarray". Поэтому, используя компилятор с поддержкой С++ 14, мы можем начать писать что-то вроде:
void func(int n)
{
int arr[n];
}
Или используйте dynarray:
#include <dynarray>
void func(int n)
{
std::dynarray<int> arr(n);
}
Я попытаюсь объяснить это с помощью примера:
Скажите, что у вас есть эта функция:
int myFunc() {
int n = 16;
int arr[n];
int k = 1;
}
Когда программа запускается, она устанавливает переменные таким образом в стек:
- n @relative addr 0
- arr[16] @relative addr 4
- k @relative addr 64
TOTAL SIZE: 68 bytes
Скажем, я хочу изменить размер arr на 4 элемента. Я собираюсь сделать:
delete arr;
arr = new int[4];
Теперь: если я оставлю стек таким образом, в стеке будут отверстия неиспользуемого пространства. Поэтому наиболее разумной задачей является перемещение всех переменных из одного места в другое в стеке и перекомпоновка их позиций. Но нам что-то не хватает: С++ не устанавливает позиции "на лету", это делается только один раз, когда вы скомпилируете программу. Зачем? Это просто: поскольку нет реальной потребности в объектах с переменными размерами в стеке, а потому, что при их распределении/перераспределении пространства стека они будут замедлять все программы.
Это не единственная проблема, есть еще одна, еще большая: Когда вы выделяете массив, вы определяете, сколько места он займет, и компилятор может предупредить вас, если вы превысите доступное пространство, вместо этого, если вы позволяете программе выделять массивы переменных размеров в вашем стеке, вы открываете нарушения в безопасности, так как вы сделать все программы, которые используют этот метод, уязвимы для.
Потому что спецификация языка так говорит. Ничего другого не имеет значения (и объяснение сегментами является ужасно неправильным по разным причинам).
Простой ответ: потому что он не определен в стандарте С++.
Не так просто ответить: потому что в этом случае никто не утверждал что-то поведение когерентно для С++. Из стандартов POV нет стека, он может быть реализован совершенно по-другому. C99 имеет VLA, но они кажутся настолько сложными для реализации, что gcc только завершил реализацию в 4.6. Я не думаю, что многие люди захотят что-то предложить для С++ и увидеть, как производители компиляторов борются с ним в течение многих лет.
Стеки довольно малы, и их размеры могут сильно варьироваться в зависимости от архитектуры. Проблема в том, что довольно легко "перераспределять" и вызывать сбои seg или записывать на память, принадлежащую кому-то другому. Между тем решения проблемы (например, vector
) существовали в течение длительного времени.
FWIW, я прочитал, что Страуструп говорит, что он не хотел их, но я не знаю, в каком интервью он был.
Потому что в С++ статический массив нуждается в статическом постоянном размере, поэтому язык не допускается. Обратите внимание, что C99 поддерживает vararrays в стеке, а некоторые реализации поддерживают его под С++, а также расширение.