Dダイナミックアレイの初期化、ストライド、インデックス操作
質問
申し訳ありませんが、これは配列に関する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){
//...
}
}
アレイは本質的にメモリブロックとサイズフィールドへのポインターフィールドを持つ構造体であることを忘れないでください