Как инициализировать статические массивы в 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]; не будет ничего выделять в куче

Другие вопросы по тегам