- PVSM.RU - https://www.pvsm.ru -
Одногруппник прислал C++-код с какой-то ошибкой и вывод компилятора по этому поводу. Но более всего меня удивила не его проблема, а то, что в коде создавался на стеке массив с неизвестной на этапе компиляции длиной. Помнится, в начале изучения языка столкнулся с этим и уяснил, что так делать нельзя. Странно, но других ошибок компилятор одногруппника не выдал…
Где-то читал, что следующий Стандарт C++14, возможно, позволит выполнять такой трюк. Но настоящий говорит, что размер массива должен быть constant expression. Это еще раз уменьшает совместимость с C99, где VLAs давно доступны.
Я использую GCC 4.8.1, поэтому на нем решил проверить:
void foo( int n)
{
int array[n];
}
Компилятор с опцией -pedantic честно выдал:
warning: ISO C++ forbids variable length array ‘array’.
На самом деле, VLAs для C++ в gcc являются расширением [1].
Самое важное, что оператор sizeof считает размер массивов переменной длины в рантайме, а не в компайлтайме. Поэтому, например, мы не сможем инстанцировать шаблон с параметром-нетипом с помощью такого sizeof( vla ):
template <int p>
class A
{
};
void foo(int length)
{
int const_lenght_array[7];
int variable_length_array[length];
A<sizeof(const_lenght_array)> a1; //OK
A<sizeof(variable_length_array)> a2; //ERROR
}
Сообщение компилятора об ошибке славно отвечает, каким образом вычисляется в рантайме размер массива:
error: ‘(unsigned int)((((sizetype)(((ssizetype)length) + -1)) + 1u) * 4u)’ is not a constant expression
Также можно использовать указатели на массивы переменной длины и typedef:
int (*p)[length] = &variable_length_array;
typedef int variable_int_array_t [length];
Более всего сказанного, GNU-расширение позволяет создавать массивы переменной длины массивов переменной длины, что не позволено даже для new, где только верхний уровень может иметь переменную длину:
void bar(int a, int b)
{
int auto_array[a][b]; //OK
int (*dynamic_array)[b] = new int[a][b]; //ERROR
}
Хорошая новость, что в C++14 будут введены VLAs, только во многом не совместимые c VLAs данного расширения и C99. По крайней мере, sizeof и typedef/using(c++11) для них будет ill-formed. Это позволит не наступить на грабли, ожидать от sizeof только компайлтайм-поведения. Вот ссылка [2] на патч для gcc.
Я знаю, что многие считают, что VLAs в C++ становятся бесполезными: для подобных целей существует vector, и никому не интересно, где в действительности выделяется память под элементы. Тем не менее, целью статьи ставилось показать такую возможность у gcc, чтобы впоследствии не удивиться.
В заключение, предложение [3] о VLAs в open-std.
Автор: abikineev
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/44252
Ссылки в тексте:
[1] расширением: http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html
[2] ссылка: http://gcc.gnu.org/ml/gcc-patches/2013-05/msg00445.html
[3] предложение: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3639.html
[4] Источник: http://habrahabr.ru/post/195148/
Нажмите здесь для печати.