auto array = new Foo[100];
我的第一个问题是这在内部是怎样的?我假设:
如果Foo是一个类,那么数组是一个指向foo对象vector<Foo*> v //c++
指针数组的指针
如果Foo是一个struct,那么array是一个指向Foo对象数组的指针。 vector<Foo> v //c++
D中的动态数组是否像C ++一样在内存中连续?
答案 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 MyClass
。 http://dlang.org/traits.html#classInstanceSize但是D通过引用来做类,因为在继承存在的情况下更容易保持理智。无论如何,我可能比你实际想要/需要的更详细,但简而言之,你对__traits(classInstanceSize, Foo)
发生的事情是正确的,并且D动态数组的布局类似于C ++向量。两者之间最大的区别是C ++向量可以与assign运算符一起复制,它是一个值类型。 D数组总是被切片 - 长度和指针(记住这篇文章中的第一个布局)被复制,但内容不是。您需要使用Foo
或array.dup
明确复制D中的数据。
进一步阅读:
foo[] = bar[]
内容,&#34;阵列属性&#34;有foo[] = bar[]
,还有更多内容< / LI>
http://dlang.org/d-array-article.html(谈论数组本身与你操作的切片,并解释一些关于动态数组内存管理的内部结构)
http://dlang.org/struct.html(您可以在那里找到有关结构对齐内容的信息)
答案 1 :(得分:4)