2013-11-26 24 views

回答

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 

从纯函数返回的可变数据是通常禁止隐式转换为不可变的异常:由于它来自纯函数,因此编译器知道它是唯一引用,并且在请求时将其视为不可变的。

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

静态阵列是一种选择,但长度需要在编译时已知:

int[100] int_array = void; // works, contents uninitialized, non-resizable, but length must be known at compile time 

一种可能的策略有声明一个大int_array_buffer,然后设置INT_ARRAY = int_array_buffer [0 ..长度] 。尽管如此,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 
} 

当它传递给函数,你可以通过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 
} 

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

+0

这很有趣! – Bauss

2

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

+0

呃,如果GC.malloc足够好的话,最好使用'T [] a; a.length = whatever;'因为这比处理void *'好一点。 –