如何创建具有设置大小但未设置值的数组?

时间:2013-11-26 21:06:06

标签: arrays d

如何创建一个具有设置大小的数组,该数组在编译时是未知的,但是具有未设置的值?

基本上我想要像int immutable([length]);这样的东西。编译时不知道length。显然,这不会编译。

2 个答案:

答案 0 :(得分:6)

它必须是用户定义的。 D中的内置数组要么是静态的,需要在编译时知道,要么切片成动态数组,可以调整大小。

内置选项:

int length = 100;
int[] int_array = new int[length]; // works, contents will be initialized to zero

这与:

相同
int[] int_array;
int_array.length = length;

如果你愿意,你也可以immutable(int)[],但是你将无法设置内容...正常的方法是编写一个创建和设置内容的纯函数在一个可变数组中,然后返回它:

pure int[] make_array(int length) {
    int[] array;
    array.length = length;
    foreach(i, ref item; array)
            item = i; // initialize it to a simple count
    return array;
}

// usage:
immutable(int)[] arr = make_array(100); // works
immutable(int[]) iarr = make_array(100); // also works

从纯函数返回的可变数据是一般禁止隐式转换为imuutable的例外:因为它来自纯函数,编译器知道它是一个唯一引用,并且可以根据请求安全地视为不可变。 / p>

第一和第二行使用之间的区别是第一行可以重新分配:arr = something_else[]; /* cool */而第二行根本不能改变。int[100] int_array = void; // works, contents uninitialized, non-resizable, but length must be known at compile time 没有长度变化,没有内容变化,没有重新分配。

静态数组是一个选项,但需要在编译时知道长度:

struct MyArray(T) {
     @disable this(); // disallow default construction; force a length
     // this constructor takes a runtime length and allocates the backing
     this(size_t length) { backing = new T[length]; }
     private T[] backing = void; // actually holds the data, uninitialized
     T[] opSlice() { return backing; } // allow easy conversion to a slice
     alias opSlice this; // implicit conversion to slice
}

一种可能的策略是声明一个大的int_array_buffer,然后设置int_array = int_array_buffer [0 .. length]。尽管如此,int_array仍然可以自行调整大小。

要获得所需的一切,它必须是用户定义的类型。这些线路可以单独使用:

void main() {
    int length = 100; // runtime
    // MyArray!int uninitialized; // compile error thanks to @disable this
    MyArray!int uninitialized = void; // ok, explicitly uninitialized
    uninitialized = MyArray!int(length); // created

    // or
    auto my_array = MyArray!int(length); // also creates it

    // my_array.length = 20; // compile error "my_array.opSlice().length is not an lvalue" - it is not resizable
    // my_array ~= 1; // compile again, "cannot append type int to type MyArray!int" - again because it is not resizable

    int[] slice = my_array; // works, makes passing it to functions that expect normal arrays easy
}

将函数传递给函数时,可以传递MyArray!int或普通的int []。多亏了别名,它将隐式转换为int [],并且由于D切片规则,即使切片在该函数中调整大小,也不会影响MyArray实例。

让我们看看一些用法:

{{1}}

那应该可以满足你所需要的一切。使用D中的包装结构,您可以选择性地启用和禁用基础类型的功能,而不会降低效率。

答案 1 :(得分:2)

不需要包装(除非我误解)。只需使用http://dlang.org/phobos/core_memory.html中的分配原语。你可以得到一大块内存,它本质上是你想要的任何未初始化的数组。