Domanda

Mi dispiace, questa è diventata una domanda di 3 volte per quanto riguarda gli array

Penso che gli array (dinamici) siano davvero potenti in D, ma quanto segue mi ha infastidito per un po ':

In C ++ potrei facilmente allocare un array con valori designati, ma in DI non ho trovato il modo di farlo. Sicuramente quanto segue non è un problema:

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

Ma sembra inefficiente, poiché la linea si inizializza con 0, e come 2 con a0. Potrebbe essere fatto qualcosa di simile a quanto segue in D?

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

Un'altra materia di efficienza che ho quando uso Stride in 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;
}

Sicuramente stavo pensando ingenuo che potevo semplicemente usare Stride per creare un nuovo array senza copiare i suoi elementi? Non c'è modo di farlo in D, giusto?


Quindi sono andato e mi sono simulato come se l'array fosse mentre il passo sarebbe tornato e implementato f come:

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) = ...;
    }
}

Ci sarebbe un modo per scrivere invece get (x) usando l'operatore indice get[x]? In questo modo potrei miscelare staticamente / includere il ciglio get funzione e mantenere il resto della funzione simile. Sarei interessato all'approccio adottato, dal momento che una struttura locale non è consentita di accedere alle variabili dell'ambito della funzione (perché no?).

È stato utile?

Soluzione

Ma sembra inefficiente, poiché la riga si inizializza con 0 e come 2 con A0. Potrebbe essere fatto qualcosa di simile a quanto segue in D?

Uso std.array.uninitializedArray

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

Sicuramente stavo pensando ingenuo che potevo semplicemente usare Stride per creare un nuovo array senza copiare i suoi elementi? Non c'è modo di farlo in D, giusto?

La tua funzione f ha un S[] come argomento, che è diverso da ciò stride ritorna. Il modo D per risolverlo è fare il tuo f funzione accetta qualsiasi intervallo rendendolo un modello:

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

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

In alternativa puoi copiare l'array:

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

Ma probabilmente vuoi evitare di copiare l'intero array se è grande.


Ci sarebbe un modo per scrivere invece get (x) usando l'operatore indice get [x]? In questo modo potrei miscelare staticamente / includere la funzione di ovarsi e mantenere il resto della funzione simile. Sarei interessato all'approccio adottato, dal momento che una struttura locale non è consentita di accedere alle variabili dell'ambito della funzione (perché no?).

È possibile sovraccaricare l'operatore di indicizzazione nella propria struttura.

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;
}

Questo è (un po ') il modo in cui il vero stride La funzione funziona. Consiglierei di leggere Gamme.

Altri suggerimenti

È possibile duplicare (creare una copia di) un array con .Dup (questo funzionerà anche con le sezioni) oppure è possibile impostare gli elementi con l'inizializzatore dell'array

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

Puoi fare che il generico (Stride () restituisce una struttura su cui puoi iterare, non un array)

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

Ricorda che gli array sono essenzialmente strutture con un campo puntatore per un blocco di memoria e un campo di dimensioni

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top