Что такое макет памяти динамических массивов?
auto array = new Foo[100];
мой первый вопрос: как это выглядит внутри? Что я предполагаю:
Если Foo является классом, то array является указателем на массив указателя объектов foo vector<Foo*> v //c++
Если Foo является структурой, то array является указателем на массив объектов Foo. vector<Foo> v //c++
является ли динамический массив в D непрерывным в памяти, как в C++?
2 ответов
динамический массив 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
работает как указатель, так как Foo*
массив в C++ - T.sizeof
когда T-класс всегда равен к void*.sizeof
* работа объекты по ссылке. Если это структура, то все на месте, как vector<Foo>
в C++.
забавный факт со структурами 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)
к за пределами в структуру: align(1) struct Foo { /* ... */ }
. Потом Фу.sizeof == 6 и в массиве нет заполнения.
- если вы хотите получить размер самого объекта, например, если вы пишете свой вариант
new MyClass
, есть способ сделать это:__traits(classInstanceSize, Foo)
. http://dlang.org/traits.html#classInstanceSize Но D делает классы по ссылке, потому что легче сохранить здравомыслие при наличии наследования.
В Любом Случае, Я вероятно, более подробно, чем вы на самом деле хотели/нуждались, но, короче говоря, вы правы о том, что происходит с Foo
и динамический массив D выложен аналогично вектору C++. Самое большое различие между ними-это вектор C++, который можно скопировать с помощью оператора assign, это тип значения. Массив D всегда будет просто разрезан - длина и указатель (помните первый макет в этом посте) копируются, но содержимое не копируется. Необходимо явно скопировать данные в D с array.dup
или foo[] = bar[]
.
читайте далее:
-
http://dlang.org/arrays.html ("операции с массивом" - это
foo[] = bar[]
материал "свойства блока" присвоенdup
и многое другое В есть) - http://dlang.org/abi.html (см. заголовок "массивы" - это описывает макет length/ptr)
http://dlang.org/d-array-article.html (рассказывает о массиве сама против среза вами манипулируют и объясняет некоторые внутренности о динамическом управлении памятью массива)
http://dlang.org/struct.html (вы можете найти информацию о выравнивании структуры там)
- Это структура, с size_t length
и Foo* ptr
это описано в http://dlang.org/abi.html (Ищите массивы)
и да, хранилище находится в непрерывной памяти.