Каково байтовое выравнивание элементов в std :: vector <char>? - PullRequest
5 голосов
/ 07 сентября 2010

Я надеюсь, что элементы выровнены на 1 байт, и, аналогично, std::vector<int> выровнен на 4 байта (или любой другой размер int на конкретной платформе).

Кто-нибудь знаетКак выровнять контейнеры стандартной библиотеки?

Ответы [ 5 ]

9 голосов
/ 07 сентября 2010

Элементы контейнера имеют по крайней мере выравнивание, требуемое для них в этой реализации: если int выровнено по 4 в вашей реализации, то каждый элемент vector<int> является int и, следовательно, 4- выровнены. Я говорю «если», потому что есть разница между требованиями к размеру и выравниванию - просто потому, что int имеет размер 4, вовсе не обязательно означает, что он должен быть выровнен по 4, что касается стандарта. Однако это очень распространено, поскольку int - это обычно размер слова машины, и большинство машин имеют преимущества для доступа к памяти на границах слов. Поэтому имеет смысл выровнять int, даже если это не является строго необходимым. Например, на x86 вы можете получить доступ к памяти без выравнивания по размеру слова, но это медленнее, чем выравнивание. На ARM недопустимые операции с текстом не разрешены, и, как правило, происходит сбой.

vector гарантирует непрерывное хранение, поэтому между первым и вторым элементом vector<char> не будет никакого "заполнения", если это то, что вас беспокоит. Особое требование для std::vector таково для 0 < n < vec.size(), &vec[n] == &vec[0] + n.

[Edit: этот бит теперь не имеет значения, спрашивающий снял неоднозначность: сам контейнер обычно будет иметь любое выравнивание, требуемое для указателя, независимо от того, что является значением value_type. Это потому, что сам вектор обычно не содержит никаких элементов, но будет иметь указатель на некоторую динамически распределенную память с элементами в нем. Это явно не требуется, но это предсказуемая деталь реализации.]

Каждый объект в C ++ выровнен по 1, единственными вещами, которые не являются битовыми полями, и элементами безумного особого случая, который является vector<bool>. Так что вы можете быть уверены, что ваша надежда на std::vector<char> обоснована. И вектор, и его первый элемент, вероятно, также будут выровнены по 4; -)

Что касается их выравнивания - точно так же, как и все в C ++, выравнивается. Когда память выделяется из кучи, она должна быть достаточно выровнена для любого объекта, который может вписаться в выделение. Когда объекты помещаются в стек, компилятор отвечает за разработку макета стека. Соглашение о вызовах будет указывать выравнивание указателя стека при входе в функцию, затем компилятор знает требования к размеру и выравниванию каждого объекта, который он устанавливает, поэтому он знает, нуждается ли стек в заполнении, чтобы привести следующий объект к правильному выравниванию.

2 голосов
/ 07 сентября 2010

Я надеюсь, что элементы выровнены на 1 байт и аналогично тому, что std :: vector выровнен на 4 байта (или любой другой размер int на конкретной платформе).

Проще говоря, std::vector - это оболочка для массива C.Элементы вектора выровнены так, как если бы они были в массиве: элементы гарантированно занимают непрерывный блок памяти без каких-либо добавленных пробелов и т. Д., Так что к std::vector<N> v можно обращаться как к массиву C с использованием &v[0].(Почему vector иногда перераспределяет хранилище, когда к нему добавляются элементы.)

Кто-нибудь знает, как выравниваются контейнеры стандартной библиотеки?

Выравнивание элементов зависит от платформы.но обычно простая переменная выравнивается так, что ее адрес делится на ее размер (естественное выравнивание).Структуры и т. Д. Дополняются (пустое пространство-заполнитель в конце) наибольшим типом данных, который они содержат, чтобы гарантировать, что если структура будет помещена в массив, все поля сохранят свое естественное выравнивание.

Для других контейнеров (подобно std::list или std::map) данные использования через шаблонную механику становятся частью внутренней структуры, а структура распределяется оператором new.new гарантировано (пользовательская реализация также должна подчиняться правилу; унаследовано от malloc()) для возврата блока памяти, который выровнен по наибольшему доступному примитиву типа данных (*).Это означает, что независимо от того, какая структура или переменная будет размещена в блоке памяти, к ней будут обращаться согласованно.В отличие от std::vector, очевидно, что элементы большинства других контейнеров STL не обязательно находятся в одном и том же непрерывном блоке памяти: они new редактируются один за другим, а не new[].

(*) В соответствии со стандартом C ++, «Функция выделения (basic.stc.dynamic.allocation) вызывается выражением new (expr.new) для выделения байтов размера, соответствующим образом выровненных для представления любого объекта такого размера».Это более мягкое требование по сравнению с одним malloc(), как правило, соблюдается в соответствии с POSIX: «Указатель, возвращаемый в случае успешного выделения, должен быть соответствующим образом выровнен, чтобы его можно было назначить указателю на любой тип объекта [...]»,Требование C ++ каким-то образом усиливает естественное требование выравнивания: динамически выделенный char будет выровнен, как требуется char, но не более.

1 голос
/ 07 сентября 2010

Вы имеете в виду элементы вектора или саму векторную структуру?Члены гарантированно будут смежными в памяти, но выравнивание структуры зависит от платформы / компилятора.В Windows это можно установить во время компиляции, а также переопределить, используя #pragma pack().

Ответ для других контейнеров, вероятно, не такой, как для вектора, поэтому я бы задал конкретные вопросы о тех, которые вас интересуют.

0 голосов
/ 07 сентября 2010

Если требуется специальное (гарантированное) выравнивание, используйте простые массивы или напишите / адаптируйте некоторый общий класс массива с помощью:

// allocation
char* pointer = _mm_malloc(size, alignment);
// deallocation
_mm_free(pointer);
0 голосов
/ 07 сентября 2010

Выравнивание всего контейнера зависит от реализации.Обычно он имеет размер как минимум (void *), то есть 4 или 8 байт в зависимости от платформы, но может быть больше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...