D Динамическая инициализация массива, шаг и операция индекса

StackOverflow https://stackoverflow.com/questions/8363728

  •  27-10-2019
  •  | 
  •  

Вопрос

Извините, это стало в трехкратный вопрос относительно массивов

Я думаю, что (динамические) массивы действительно сильны в D, но следующее меня какое -то время беспокоило:

В C ++ я мог легко выделить массив с назначенными значениями, но в DI не нашел способ сделать это. Конечно, следующее не является проблемой:

int[] a = new int[N];
a[] = a0;

Но это выглядит неэффективно, поскольку первая линия будет инициализироваться с 0, и как 2 с a0. Анкет Можно ли сделать что -то похожее на следующее в D?

int[] a = new int(a0)[N]; // illegal

Еще один вопрос эффективности, который у меня есть при использовании шага в std.range:

import std.stdio;
import std.range;

struct S
{
    int x;

    this(this)
    {
        writeln("copy ", x);
    }
}

void f(S[] s)
{
}

int main()
{
    S[] s = new S[10];
    foreach (i, ref v; s)
    {
        v.x = i;
    }

    f(stride(s, 3)); // error
    return 0;
}

Конечно, я был наивен, думая, что могу просто использовать шаг, чтобы создать новый массив, не копируя его элементы? В D нет способа сделать это, верно?


Поэтому я пошел и смоделировал, как если бы массив был так же, как и шаг, и реализовано f в качестве:

f(s, 3);

void f(S[] s, uint stride)
{
    ref S get(uint i)
    {
        assert (i * stride < s.length);
        return s[i * stride];
    }

    for (uint x ... )
    {
        get(x) = ...;
    }
}

Будет ли способ вместо этого написать (x), используя оператор индекса get[x]? Таким образом, я мог бы статически смешать / включить ход get функционируйте и держите остальную часть функции одинаковой. Я был бы заинтересован в принятом подходе, поскольку локальной структуре не разрешается получить доступ к переменным сферу функции (почему бы и нет?).

Это было полезно?

Решение

Но это выглядит неэффективно, так как первая линия будет инициализироваться с 0, а 2 - с A0. Можно ли сделать что -то похожее на следующее в D?

Использовать std.array.uninitializedArray

S[] s = uninitializedArray!(S[])(N);
s[] = a0; 

Конечно, я был наивен, думая, что могу просто использовать шаг, чтобы создать новый массив, не копируя его элементы? В D нет способа сделать это, верно?

Ваша функция f имеет S[] как аргумент, который отличается от того, что stride возврат. D Способ решить это - сделать ваш f Функция принимайте любой диапазон, сделав его шаблоном:

void f(Range)(Range s)
{
    foreach (item; s)
        // use item
}

S[] s = new S[10];
f(s); // works
f(stride(s, 3)); // works too

В качестве альтернативы вы можете скопировать массив:

f(array(stride(s, 3)));

Но вы, вероятно, хотите избежать копирования всего массива, если он большой.


Будет ли способ вместо этого написать Get (x) с помощью оператора индекса GET [x]? Таким образом, я мог бы статически смешать / включить функцию ход и сохранить остальную часть функции одинаковой. Я был бы заинтересован в принятом подходе, поскольку локальной структуре не разрешается получить доступ к переменным сферу функции (почему бы и нет?).

Вы можете перегрузить оператора индексации в собственном структуре.

struct StrideArray
{
    this(S[] s, uint stride) { m_array = s; m_stride = stride; }

    S opIndex(size_t i) { return s[i * m_stride]; }
    void opIndexAssign(size_t i, S value) { s[i * m_stride] = value; }

    private S[] m_array;
    private uint m_stride;
}

Это (своего рода) способ фактического stride функция работает. Я бы порекомендовал прочитать на Диапазоны.

Другие советы

Вы можете дублировать (создать копию) массива с .dup (это также будет работать с ломтиками) или вы можете установить элементы с помощью инициализатора массива

int[] a=a0.dup;
int[] b=[e1,e2,e3];

Вы можете сделать f generic (stride () возвращает структуру, которую вы можете перевернуть, а не массив)

void f(Z)(Z s)if(isInputRange!Z){
    foreach(elem;s){
         //...
    }
}

Помните, что массивы по существу являются поставками с полем указателя в некотором блоке памяти и полем размера

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top