我在下面的代码背后有点好奇的机制:
int[3] a1 = [ 1 , 2 , 3 ];
int[3] a2 = [ 1 , 2 , 3 ];
int[3] result = a1[] + a2[];
foreach (i; result)
writeln(i);
结果是2,4,6。在C ++中,我们不得不重载'+'运算符,以便使用两个向量来实现它或使用std :: transform。我查了一下array(std_array.html)的实现文档。我无法找到'+'的任何重载,我认为D通过检查数据整数类型或其他东西来管理这个,但我只是在猜测。
有人可以解释这实际上是如何运作的吗?
答案 0 :(得分:6)
这是语言本身的一部分:
http://dlang.org/arrays.html#array-operations
只要实现结果,实现可能会做不同的事情,这为自动优化提供了足够的灵活性。目前,在查看反汇编时,它会编译为函数调用,类似于操作符重载,只是自动完成。
答案 1 :(得分:0)
我在D中的实现可能是错的,但我认为这将非常接近。
D中的井阵列由长度和指针组成。这种事情背后的机制非常简单。您基本上为默认大小分配内存,一旦数组填充了元素并附加了另一个元素,您只需重新分配内存并添加元素。
这是我做的一些快速代码。它只进行了最低限度的测试。
C库:
import std.c.stdlib : malloc, realloc, free;
import std.c.string : memcpy;
来源:
/**
* A dynamic array.
* T would be the type of the array
*/
struct DynamicArray(T) {
T* array; // A pointer to the elements of the array
size_t nextindex; // The next index
size_t size; // The size of the array
/**
* Allocates a new dynamic array with an initialization size.
*/
this(size_t size = 0) {
array = cast(T*)malloc(size * T.sizeof); // Allocates memory of the array for the default array size
nextindex = 0; // The next index is 0 (Arrays are always 0 indexed)
this.size = size; // The size of the array
}
/**
* Appends an element to the array and reallocates memory if necessary.
*/
void appendElement(T e) {
if (nextindex == size) { // If the next index is the size of the array
size++; // Add one to the size (Since we're appending one element)
array = cast(T*)realloc(array, size * T.sizeof); // Reallocate memory to fit the element
}
array[nextindex++] = e; // Adds the element to the index
}
/**
* Appends another array to the array and reallocates memory if necessary.
*/
void appendArray(DynamicArray!T a) {
// This could be done using realloc too and memcpy
foreach (i; 0 .. a.size) {
appendElement(a.array[i]);
}
}
/**
* Gets an element by index.
*/
T getByIndex(size_t index) {
return array[index];
}
/**
* Gets a string of the array elements.
*/
string toString() {
import std.string : format;
import std.array : join;
import std.conv : to;
string[] elements;
foreach (i; 0 .. size)
elements ~= to!string(getByIndex(i));
return format("[%s]", join(elements, ", "));
}
~this() {
free(array);
}
}
用法:
auto array1 = DynamicArray!int(5); // Initialize it with 5
foreach (int i; 0 .. 10) // Loops from 0 to 10, although the actual size of the array is 5
array1.appendElement(i); // Appends i to the array and expands it as necessary
writeln(array1.toString); // Prints out the array
auto array2 = DynamicArray!int(10); // Initialize it with 10
foreach (int i; 0 .. 10) // Loops from 0 to 10
array2.appendElement(i); // Appends i to the array, but does no reallocations, because the size is already 10
writeln(array2.toString); // Prints out the array
array1.appendArray(array2); // Appends array2 to array1
writeln(array1.toString); // Prints out array1
输出:
当然不应该使用这样的东西,我几乎肯定D中的动态数组的实现有点复杂和不同,但这应该让你了解它是如何完成的。
这是一个与您发布的内容相同的示例。
auto a1 = DynamicArray!int(3); // int[3] a1
// = [
a1.appendElement(1); // 1,
a1.appendElement(2); // 2,
a1.appendElement(3); // 3
// ];
auto a2 = DynamicArray!int(3); // int[3] a2
// = [
a2.appendElement(1); // 1,
a2.appendElement(2); // 2,
a2.appendElement(3); // 3
// ];
auto result = DynamicArray!int(3); // int[3] result
// result =
result.appendArray(a1); // a1
// +
result.appendArray(a2); // a2;
刚刚查看了DMD源代码,我对实现非常接近。数组实现有一个保留函数,它调用malloc / realloc,insert函数也调用reserve函数。
https://github.com/D-Programming-Language/dmd/blob/master/src/root/array.h#L76
并且
https://github.com/D-Programming-Language/dmd/blob/master/src/root/array.h#L198