Чтобы выделить память из стека или кучи для переменной, размер переменной должен быть известен. Компиляторы C ++ могут сами решать, как они распределяют память, но c ++ обнародовал, как они ожидают, что компиляторы c ++ справятся с ситуацией, и, следовательно, c ++ std требует, чтобы производители компиляторов опубликовали свою обработку памяти. Это происходит через оператор sizeof. Этот оператор полностью вычисляется во время компиляции. Ограничение времени компиляции для размеров массива вытекает из этого требования.
int arr[10];
std::cout << sizeof(arr) << std::endl
, поскольку каждая переменная и тип поддерживает sizeof, их размеры необходимо вычислять во время компиляции в c ++. Таким образом, массивы переменной длины невозможны в c ++.
Существует еще одно очень важное ограничение, вытекающее из этого требования. В принципе, поставщики компилятора c ++ могли бы рассчитать максимальный объем памяти, необходимый для стека программы c ++, если бы не было одной проблемы: для рекурсивных функций вы не можете вычислить размер стека, используемый программой, но для всего остального размер стека может рассчитать, выполнив следующее:
- использовать sizeof (a) для каждой переменной в кадре стека
- сумма размеров переменных, чтобы получить объем памяти, необходимый для этого стекового кадра
- перечислить все возможные кадры стека и рассчитать их размеры
- Выберите стек вызовов, который имеет наибольший размер
- выберите этот размер в качестве размера стека вашей программы.
К сожалению, рекурсивные функции нарушают всю схему. И для анализа того, какие функции могут иметь бесконечные стеки вызовов, потребуется анализ глобального потока программы. Но ограничение для оператора sizeof во время компиляции является важным, иначе наши программы на c ++ могли бы случайно исчерпать пространство стека, вызывая сбои и нестабильность. И это недопустимо. Таким образом, каждая переменная и тип поддерживает оператор sizeof времени компиляции.
Поддержка VLA требует, чтобы компиляторы могли генерировать код, в котором смещения, обычно генерируемые как константы результирующего машинного кода, фактически модифицируются во время выполнения. Стандартные компиляторы c ++ обычно не имеют возможности сделать это. C решил добавить эту поддержку, и таким образом компиляторы C могут это сделать. Но в процессе им нужно было сломать оператор sizeof. Размеры больше не могут быть рассчитаны во время компиляции. Поддержка VLA, как указано в стандарте C, имеет большие проблемы:
- вы не можете поместить VLA в структуру или класс
- VLA в основном ограничены локальной областью действия
Эти проблемы уже решены в c ++ с помощью std :: vector, у которых нет ни одной из этих проблем.