如何创建一个具有设置大小的数组,该数组在编译时是未知的,但是具有未设置的值?
基本上我想要像int immutable([length]);
这样的东西。编译时不知道length
。显然,这不会编译。
答案 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中的分配原语。你可以得到一大块内存,它本质上是你想要的任何未初始化的数组。