动态数组的内存布局是什么?

时间:2014-08-23 10:38:32

标签: d

auto  array =  new Foo[100];

我的第一个问题是这在内部是怎样的?我假设:

如果Foo是一个类,那么数组是一个指向foo对象vector<Foo*> v //c++指针数组的指针

如果Foo是一个struct,那么array是一个指向Foo对象数组的指针。 vector<Foo> v //c++

D中的动态数组是否像C ++一样在内存中连续?

2 个答案:

答案 0 :(得分:13)

D动态数组如下所示:

struct Array(T) {
     size_t length;
     T* ptr;
}

执行new T[size]基本上就是这样运行:

Array!T array;
array.length = size;
array.ptr = GC.malloc(size * T.sizeof);

所以,是的,元素的内存是连续的,就像在C ++中一样。你的其余部分深入探讨了T的具体内容,你对自己的想法是正确的:

如果Foo是一个类,这意味着对Foo的任何引用都像指针一样工作,所以它就像C ++中的Foo*数组 - T.sizeof当T是a时class始终等于void*.sizeof *,对象通过引用工作。如果它是一个结构,它就是就地的,就像C ++中的vector<Foo>一样。

有结构的有趣事实btw:由于对齐问题,它们不一定必须打包在数组中。请考虑以下事项:

struct Foo {
   ushort s;
   uint i;
}

Foo.sizeof你可能期望是6 ...但它实际上是8因为uint将在4字节边界上对齐,导致在s之后填充两个字节。如果您将align(1)添加到uint字段,则会覆盖此内容,将i放在内存中的s旁边。但是,既然我们正在讨论数组,那么您希望节点Foo[]元素将/仍然/仍然拥有自己的对齐... Foo.sizeof == 8仍然是Foo[2]大小为16.内部align(1)只是将填充移动到结构的末尾,对于数组的情况,它没有完全删除它。

如果您希望Foo[]在元素之间没有填充,那么您还需要将align(1)添加到结构的外部:{ {1}}。然后Foo.sizeof == 6并且阵列中没有填充。

  • 如果您想获得对象本身的大小,例如,如果您正在编写自己的align(1) struct Foo { /* ... */ }版本,那么也可以这样做:new MyClasshttp://dlang.org/traits.html#classInstanceSize但是D通过引用来做类,因为在继承存在的情况下更容易保持理智。

无论如何,我可能比你实际想要/需要的更详细,但简而言之,你对__traits(classInstanceSize, Foo)发生的事情是正确的,并且D动态数组的布局类似于C ++向量。两者之间最大的区别是C ++向量可以与assign运算符一起复制,它是一个值类型。 D数组总是被切片 - 长度和指针(记住这篇文章中的第一个布局)被复制,但内容不是。您需要使用Fooarray.dup明确复制D中的数据。

进一步阅读:

答案 1 :(得分:4)

array本身是一个包含size_t lengthFoo* ptr

的结构

http://dlang.org/abi.html(寻找数组)

中描述了这一点

是的,存储在连续的内存中。