Что такое макет памяти динамических массивов?
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 (Ищите массивы)
и да, хранилище находится в непрерывной памяти.