D 动态阵列的内存布局是什么?

D 动态阵列的内存布局是什么?,d,D,我的第一个问题是,这在内部看起来如何?我的假设是: 如果Foo是一个类,那么array是指向Foo对象指针数组的指针vector v//c++ 如果Foo是一个结构,那么array是指向Foo对象数组的指针向量v//c++ 是在D中连续的动态数组,像在C++中一样, < p> 数组< /C> >本身是一个结构,它具有 siZeIt长度< /C> >和 fo*pTr> /Calp> 这在(查找阵列)中进行了描述 是的,存储在连续内存中。D动态数组如下所示: auto array = new F

我的第一个问题是,这在内部看起来如何?我的假设是:

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

如果Foo是一个结构,那么array是指向Foo对象数组的指针<代码>向量v//c++


是在D中连续的动态数组,像在C++中一样,

< p> <代码>数组< /C> >本身是一个结构,它具有<代码> siZeIt长度< /C> >和<代码> fo*pTr> /Calp> 这在(查找阵列)中进行了描述


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

D动态数组如下所示:

auto  array =  new Foo[100];
执行
newt[size]
基本上就是执行以下操作:

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

是的,元素的内存是与C++类似的。剩下的问题是关于T是什么的细节,你的想法是对的:

<> > <代码> fo是一个类,即任何引用<代码> FoO < /C> >像指针一样工作,因此它就像C++中的“代码> Fo**/Cuffo>数组”,当T是一个类,总是等于<> >空> *sieOS/<代码> *,对象按引用工作。如果是一个结构,它是完全就位的,比如C++中的代码>向量< /代码>。 顺便说一句,结构的有趣之处在于:由于对齐问题,它们不一定打包在数组中。考虑以下事项:

Array!T array;
array.length = size;
array.ptr = GC.malloc(size * T.sizeof);
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,数组中没有填充

  • 如果您想获得对象本身的大小,例如,如果您正在编写自己版本的
    新MyClass
    ,也有一种方法可以做到这一点:
    \uu traits(classInstanceSize,Foo)
    。但是D是通过引用来实现类的,因为在存在继承的情况下更容易保持健全
<>无论如何,我可能会比你实际需要的更详细,但简而言之,你对“<代码> FoO < /Cord>”发生了什么,D动态数组与C++向量类似。两者之间最大的区别是C++向量可以复制赋值操作符,它是一种值类型。一个D数组总是被切片-长度和指针(记住本文中的第一个布局)被复制,但内容没有被复制。您需要使用
array.dup
foo[]=bar[]
显式复制D中的数据

进一步阅读:

  • (“数组操作”是
    foo[]=bar[]
    的东西,“数组属性”有
    dup
    ,还有更多)
  • (请参阅“阵列”标题-这描述了长度/ptr布局)
  • (讨论阵列本身与您操作的片,并解释有关动态阵列内存管理的一些内部内容)

  • (您可以在那里找到有关结构对齐的信息)


但是定制的
新的
也传递了所需的大小(考虑子类),这实际上是一个非常有用的答案。
struct Foo {
   ushort s;
   uint i;
}