在D语言中添加两个数组的机制

时间:2015-02-01 03:14:21

标签: arrays d

我在下面的代码背后有点好奇的机制:

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通过检查数据整数类型或其他东西来管理这个,但我只是在猜测。

有人可以解释这实际上是如何运作的吗?

2 个答案:

答案 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

输出:

Output SS

当然不应该使用这样的东西,我几乎肯定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