二维的动态数组初始化,步幅和索引操作 [英] D dynamic array initialization, stride and the index operation

查看:172
本文介绍了二维的动态数组初始化,步幅和索引操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,这成为对数组3倍的问题。

我认为(动态)阵列是在D中真正强大的,但下面已经困扰了我一段时间:

在C ++中我可以轻松地与指定的值分配一个数组,但在D我还没有找到一种方式来做到这一点。当然,下面是没有问题的:

  INT [] A = INT新[N];
一个[] = A0;

但看上去效率低,因为一行将与 0 初始化,而像2 A0 。可以与以下类似的东西在D中做什么?

  INT [] A = INT新(A0)[N]; //非法


另一个效率无论我在std.range使用时的步幅有:

 进口std.stdio;
进口std.range;的struct
{
    INT X;    这(本)
    {
        writeln(复制,X);
    }
}无效F(S [] S)
{
}诠释的main()
{
    S [] S =新S [10];
    的foreach(我,裁判伏; S)
    {
        V.X = I;
    }    F(步幅(S,3)); //错误
    返回0;
}

当然,我是天真的想法我可以简单地用步幅不复制它的元素,创造出一个新的数组?有没有办法在D中这样做,对吧?


于是我就和模拟为如果阵列作为步幅将返回,并实施˚F为:

  F(S,3);无效F(S [] S,UINT步幅)
{
    REF小号弄(UINT I)
    {
        断言(我*步幅< s.length);
        返回小号[我*步幅]
    }    对于(UINT X ...)
    {
        得到(X)= ...;
    }
}

会不会有使用索引操作符的方式,而不是写得到(X) GET [X] ?这样我可以静态地混入/包括跨步 GET 功能,并保持类似功能的其余部分。我很想在所采取的方法,因为当地的结构是不允许访问函数范围内的变量(为什么不呢?)。


解决方案

  

但看上去效率低,因为一行将与0初始化,而像2 A0。可以与以下类似的东西在D中做什么?


使用 std.array.uninitializedArray

  S [] S = uninitializedArray(S [])(N)!;
S [] = A0;



  

当然,我是天真的想法我可以简单地用步幅不复制它的元素,创造出一个新的数组?有没有办法在D中这样做,对吧?


您函数˚F有一个 S [] 作为一个参数,它是从什么<$ C $不同C>步幅的回报。对D的方式来解决,这是使你的˚F功能通过使模板接受任何范围:

 无效F(范围)(范围S)
{
    的foreach(项目; S)
        //利用项目
}S [] S =新S [10];
F(S); //作品
F(步幅(S,3)); //工程太

另外,您可以在阵列复制:

  F(阵列(步幅(S,3)));

但你可能想避免复制整个数组,如果是大的。



  

会不会有使用索引运算得到[X],而不是写得到(X)的方法吗?这样我可以静态地混入/包括跨越式get函数,并保持类似功能的其余部分。我很想在所采取的方法,因为当地的结构是不允许访问函数范围内的变量(为什么不呢?)。


您可以在自己的结构重载索引运算符。

 结构StrideArray
{
    该(S [] S,UINT步幅){m_array = S; m_stride =步幅; }    小号opIndex(为size_t我){返回小号[我* m_stride] }
    无效opIndexAssign(为size_t I,S值){S [I * m_stride] =价值; }    私人S [] m_array;
    私人UINT m_stride;
}

这是(种)的实际步幅函数的工作方式。我建议你​​在范围读了。

Sorry, this became a 3-fold question regarding arrays

I think (dynamic) arrays are truly powerful in D, but the following has been bothering me for a while:

In C++ I could easily allocate an array with designated values, but in D I haven't found a way to do so. Surely the following is no problem:

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

But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?

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


Another efficiency matter I have when using stride in 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;
}

Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?


So I went and simulated as if the array was as stride would return, and implemented f as:

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

Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).

解决方案

But it looks inefficient, since line one will initialize with 0, and like 2 with a0. Could something similar to the following be done in D?

Use std.array.uninitializedArray

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


Surely I was naive thinking I could simply use stride to create a new array without copying it's elements? There is no way to do so in D, right?

Your function f has an S[] as an argument, which is different from what stride returns. The D way to solve this is to make your f function accept any range by making it a template:

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

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

Alternatively you can copy the array:

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

But you probably want to avoid copying the entire array if it is large.


Would there be a way to instead write get(x) using the index operator get[x]? This way I could statically mixin / include the striding get function and keep the rest of the function similar. I'd be interested in the approach taken, since a local struct is not allowed to access function scope variables (why not?).

You can overload the indexing operator in your own struct.

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

This is (kind of) the way the actual stride function works. I'd recommend reading up on Ranges.

这篇关于二维的动态数组初始化,步幅和索引操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆