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

Jer*_*oen 2 arrays d

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

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

Ada*_*ppe 6

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

内置选项:

int length = 100;
int[] int_array = new int[length]; // works, contents will be initialized to zero
Run Code Online (Sandbox Code Playgroud)

这与以下相同:

int[] int_array;
int_array.length = length;
Run Code Online (Sandbox Code Playgroud)

你也可以这样做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
Run Code Online (Sandbox Code Playgroud)

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

第一行和第二行使用之间的差异是第一行可以重新分配:arr = something_else[]; /* cool */而第二行根本不能改变.没有长度变化,没有内容变化,没有重新分配.

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

int[100] int_array = void; // works, contents uninitialized, non-resizable, but length must be known at compile time
Run Code Online (Sandbox Code Playgroud)

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

要获得您想要的一切,它必须是用户定义的类型.这些线条可以单独使用:

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
}
Run Code Online (Sandbox Code Playgroud)

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

我们来看看一些用法:

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
}
Run Code Online (Sandbox Code Playgroud)

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