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

Mai*_*ein 8 d

auto  array =  new Foo[100];
Run Code Online (Sandbox Code Playgroud)

我的第一个问题是内部如何看待?我假设:

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

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

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

Ada*_*ppe 13

AD动态数组如下所示:

struct Array(T) {
     size_t length;
     T* ptr;
}
Run Code Online (Sandbox Code Playgroud)

new T[size]的基本上就是这样:

Array!T array;
array.length = size;
array.ptr = GC.malloc(size * T.sizeof);
Run Code Online (Sandbox Code Playgroud)

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

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

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

struct Foo {
   ushort s;
   uint i;
}
Run Code Online (Sandbox Code Playgroud)

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

如果你想要一个Foo[]在元素之间没有填充的东西,你也想要添加align(1)到结构的外部:align(1) struct Foo { /* ... */ }.然后Foo.sizeof == 6并且数组中没有填充.

  • 如果你想获得对象本身的大小,例如,如果你正在编写自己的版本new MyClass,那么也有办法:__traits(classInstanceSize, Foo).http://dlang.org/traits.html#classInstanceSize但是D通过引用来完成类,因为在继承存在的情况下更容易保持理智.

无论如何,我可能比你实际想要/需要的更详细,但简而言之,你对于发生的事情是正确的,Foo并且D动态数组的布局类似于C++向量.两者之间最大的区别是C++向量可以与assign运算符一起复制,它是一个值类型.AD数组将始终被切片 - 复制长度和指针(记住此帖中的第一个布局),但内容不是.您需要使用array.dup或显式复制D中的数据foo[] = bar[].

进一步阅读: