Dダイナミックアレイの初期化、ストライド、インデックス操作

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

  •  27-10-2019
  •  | 
  •  

質問

申し訳ありませんが、これは配列に関する3倍の質問になりました

(動的)アレイはDで本当に強力だと思いますが、以下はしばらく私を悩ませてきました。

C ++では、指定された値で配列を簡単に割り当てることができましたが、DIではそうする方法が見つかりませんでした。確かに次のことは問題ありません:

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

しかし、行1は初期化されるため、非効率的に見えます 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;
}

確かに、私は単にStrideを使用して、それが要素をコピーせずに新しい配列を作成できると思っていましたか? 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) = ...;
    }
}

インデックス演算子を使用して代わりにget(x)を書き込む方法はありますか get[x]?このようにして、私は静的にミックス /ストライディングを含めることができます get 関数と機能の残りの部分を同様に保ちます。ローカル構造体は関数スコープ変数にアクセスすることが許可されていないため、採用されたアプローチに興味があります(なぜですか?)。

役に立ちましたか?

解決

ただし、行1は0で初期化され、A0で2のように初期化されるため、非効率的に見えます。次のようなことはDで行うことができますか?

使用する std.array.uninitializedArray

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

確かに、私は単にStrideを使用して、それが要素をコピーせずに新しい配列を作成できると思っていましたか? Dでそうする方法はありませんよね?

あなたの機能 f 持っています S[] 議論として、それは何とは異なります stride 戻り値。これを解決する方法はあなたを作ることです 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)を書き込む方法はありますか?このようにして、ストライディングゲット機能を静的に混合 /含めることができ、関数の残りの部分を同様に保つことができます。ローカル構造体は関数スコープ変数にアクセスすることが許可されていないため、採用されたアプローチに興味があります(なぜですか?)。

インデックスオペレーターに独自の構造体を過負荷できます。

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