Что такое макет памяти динамических массивов?

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 (вы можете найти информацию о выравнивании структуры там)

  • http://wiki.dlang.org/Books


- Это структура, с size_t length и Foo* ptr

это описано в http://dlang.org/abi.html (Ищите массивы)

и да, хранилище находится в непрерывной памяти.