很抱歉,这成了关于数组的三重问题
我认为(动态)数组在D中真正强大,但以下一直困扰我一段时间:
在C ++中,我可以很容易地分配一个带有指定值的数组,但是在D中我还没有找到一种方法。当然以下是没有问题的:
int[] a = new int[N];
a[] = a0;
但它看起来效率低下,因为第一行将使用0
进行初始化,而使用a0
进行初始化。在D中可以做类似以下的事情吗?
int[] a = new int(a0)[N]; // illegal
在std.range中使用stride时我遇到的另一个效率问题:
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) = ...;
}
}
是否有办法使用索引运算符get[x]
来编写get(x)?这样我就可以静态混合/包含跨步get
函数并保持函数的其余部分相似。我对所采用的方法感兴趣,因为不允许本地结构访问函数范围变量(为什么不呢?)。
答案 0 :(得分:7)
但它看起来效率低下,因为第一行将初始化为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)?这样我就可以静态地混合/包含跨步的get函数并保持函数的其余部分相似。我对所采用的方法感兴趣,因为不允许本地结构访问函数范围变量(为什么不呢?)。
您可以在自己的结构中重载索引操作符。
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
函数的工作方式。我建议您阅读Ranges。
答案 1 :(得分:1)
你可以复制(创建一个)带有.dup的数组(这也适用于切片),或者你可以使用数组初始化器设置元素
int[] a=a0.dup;
int[] b=[e1,e2,e3];
你可以使f泛型(stride()返回一个可以迭代的结构,而不是数组)
void f(Z)(Z s)if(isInputRange!Z){
foreach(elem;s){
//...
}
}
请记住,数组本质上是带有指向某个内存块的指针字段和大小字段
的结构