Frage

Entschuldigung, dies wurde zu einer dreifachen Frage zu Arrays

Ich denke, (dynamische) Arrays sind in D wirklich mächtig, aber das folgende stört mich schon seit einiger Zeit:

In C ++ konnte ich leicht ein Array mit festgelegten Werten zuweisen, aber in DI hat ich keinen Weg gefunden, dies zu tun. Sicherlich ist Folgendes kein Problem:

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

Aber es sieht ineffizient aus, da Zeile eins mit initialisieren wird 0, und wie 2 mit a0. Könnte etwas Ähnliches wie folgt in D gemacht werden?

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

Eine weitere Effizienz -Angelegenheit, die ich bei der Verwendung von Strid in Std.Range habe:

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

Sicherlich war ich naiv und dachte, ich könnte einfach Schritt verwenden, um ein neues Array zu erstellen, ohne seine Elemente zu kopieren? Es gibt keine Möglichkeit, dies in D zu tun, oder?


Also ging ich und simulierte, als ob das Array so wäre, wie sie zurückkehren würde, und implementiert f wie:

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

Würde es eine Möglichkeit geben, stattdessen Get (X) mit dem Indexoperator zu schreiben get[x]? Auf diese Weise konnte ich mich statisch mischen / den Schritt einschließen get Funktion und halten Sie den Rest der Funktion ähnlich. Ich würde mich für den Ansatz interessieren, da eine lokale Struktur nicht zugreifen kann, um Funktionsumfangsvariablen zuzugreifen (warum nicht?).

War es hilfreich?

Lösung

Aber es sieht ineffizient aus, da Zeile 1 mit 0 initialisiert und 2 mit A0 initialisiert wird. Könnte etwas Ähnliches wie folgt in D gemacht werden?

Verwenden std.array.uninitializedArray

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

Sicherlich war ich naiv und dachte, ich könnte einfach Schritt verwenden, um ein neues Array zu erstellen, ohne seine Elemente zu kopieren? Es gibt keine Möglichkeit, dies in D zu tun, oder?

Ihre Funktion f hat an S[] als Argument, das sich von was unterscheidet als was stride kehrt zurück. Die Möglichkeit, dies zu lösen, besteht darin, Ihre zu machen f Funktion akzeptieren jeden Bereich, indem Sie es zu einer Vorlage machen:

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

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

Alternativ können Sie das Array kopieren:

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

Aber Sie möchten wahrscheinlich vermeiden, das gesamte Array zu kopieren, wenn es groß ist.


Würde es eine Möglichkeit geben, stattdessen Get (x) mit dem Index -Operator GET [x] zu schreiben? Auf diese Weise konnte ich die Striding -Get -Funktion statisch mischen / einschließen und den Rest der Funktion ähnlich halten. Ich würde mich für den Ansatz interessieren, da eine lokale Struktur nicht zugreifen kann, um Funktionsumfangsvariablen zuzugreifen (warum nicht?).

Sie können den Indizierungsoperator in Ihrer eigenen Struktur überladen.

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

Dies ist (irgendwie) die Art der tatsächlichen Art stride Funktion funktioniert. Ich würde empfehlen, weiterzulesen Bereiche.

Andere Tipps

Sie können ein Array mit .DUP (dies auch mit Scheiben erstellen) duplizieren (erstellen) oder Sie können die Elemente mit dem Array -Initialisierer festlegen

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

Sie können den generischen (Stride () eine Struktur zurückgeben, über die Sie iterieren können, nicht um ein Array).

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

Denken Sie daran, dass Arrays im Wesentlichen Strukturen mit einem Zeigerfeld auf einen Speicherblock und ein Größenfeld sind

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top