Как инициализировать статические массивы в D без выделения GC?
В D все литералы массива являются динамическими массивами и поэтому выделяются GC.
Даже в этом простом примере:
int[3] a = [10, 20, 30];
Массив выделяется в куче, а затем копируется в a
,
Как вы должны инициализировать статический массив без выделения кучи?
Вы можете сделать это вручную:
int[3] a = void;
a[0] = 10;
a[1] = 20;
a[2] = 30;
Но это в лучшем случае утомительно.
Есть ли способ лучше?
5 ответов
static const int[3] a = [10, 20, 30];
Это поместит постоянную копию в сегмент данных. Вы можете создать копию в стеке (без выделения кучи) с помощью простого назначения (auto copy = a;
).
Я думаю, что если бы вы могли объявить литерал как immutable
глобально, затем используйте это как инициализатор, там нет выделения кучи - но я могу ошибаться, я не уверен.
Это просто ошибка компилятора. Я видел это в багзилле DMD. Это должно быть исправлено (DMD 2.055).
ОБНОВЛЕНИЕ 2017: В любой недавней версии DMD использование инициализатора массива в статическом массиве больше не выделяется, даже если статический массив является локальной переменной (то есть размещается в стеке).
Вы можете проверить это самостоятельно, создав функцию, в которой инициализируется статический массив, а затем пометив функцию как @nogc и наблюдая, компилируется ли она. Пример:
import std.random;
import std.stdio;
int[4] testfunc(int num) @nogc
{
return [0, 1, num, 3];
}
int main()
{
int[4] arr = testfunc(uniform(0, 15));
writeln(arr);
return 0;
}
Поскольку testfunc() компилируется, несмотря на то, что он @nogc, мы знаем, что инициализатор массива не выделяет.
Я думаю, что вы можете немного ошибиться: в http://www.digitalmars.com/d/2.0/arrays.html
Статическая инициализация статических массивов
Статические инициализации предоставляются списком значений элементов массива, заключенных в [ ]. Значениям могут предшествовать индекс и a:. Если индекс не указан, ему присваивается предыдущий индекс плюс 1 или 0, если это первое значение.
-snip-
Эти массивы являются статическими, когда они появляются в глобальной области видимости. В противном случае они должны быть помечены с помощью const или статических классов хранения, чтобы сделать их статическими массивами.
с примером кода
int[3] a = [ 1:2, 3 ]; // a[0] = 0, a[1] = 2, a[2] = 3
это означает, что const a[3] = [10, 20, 30];
не будет ничего выделять в куче