4

抱歉,这变成了关于数组的 3-fold 问题

我认为(动态)数组在 D 中确实很强大,但是以下问题一直困扰着我一段时间:

在 C++ 中,我可以轻松地分配具有指定值的数组,但在 DI 中还没有找到这样做的方法。当然以下没有问题:

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

当然,我天真地认为我可以简单地使用 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函数并保持函数的其余部分相似。我会对所采用的方法感兴趣,因为不允许本地结构访问函数范围变量(为什么不呢?)。

4

2 回答 2

7

但它看起来效率低下,因为第一行将使用 0 进行初始化,而第二行将使用 a0 进行初始化。可以在 D 中完成类似于以下的操作吗?

采用std.array.uninitializedArray

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

当然,我天真地认为我可以简单地使用 stride 创建一个新数组而不复制它的元素?在 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

于 2011-12-03T00:25:05.583 回答
1

您可以使用 .dup 复制(创建副本)数组(这也适用于切片),或者您可以使用数组初始值设定项设置元素

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

你可以使 f 泛型(stride() 返回一个你可以迭代的结构,而不是一个数组)

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

请记住,数组本质上是具有指向某个内存块的指针字段和大小字段的结构

于 2011-12-03T00:19:01.640 回答