如何创建一个数组,其大小已设置,但在编译时不知道,但未设置值?如何创建具有设置大小但未设置值的数组?
基本上我想要的东西像int immutable([length]);
。编译时不知道length
。显然这并不能编译。
如何创建一个数组,其大小已设置,但在编译时不知道,但未设置值?如何创建具有设置大小但未设置值的数组?
基本上我想要的东西像int immutable([length]);
。编译时不知道length
。显然这并不能编译。
它必须是用户定义的。 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中的包装结构,您可以选择性地启用和禁用基础类型的功能,而不会降低效率。
不需要包装(除非我误解)。只需使用http://dlang.org/phobos/core_memory.html中的分配原语。你可以得到一大块内存,它基本上是你想要的任何未初始化的数组。
呃,如果GC.malloc足够好的话,最好使用'T [] a; a.length = whatever;'因为这比处理void *'好一点。 –
这很有趣! – Bauss