Элементы контейнера имеют по крайней мере выравнивание, требуемое для них в этой реализации: если 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 ++, выравнивается. Когда память выделяется из кучи, она должна быть достаточно выровнена для любого объекта, который может вписаться в выделение. Когда объекты помещаются в стек, компилятор отвечает за разработку макета стека. Соглашение о вызовах будет указывать выравнивание указателя стека при входе в функцию, затем компилятор знает требования к размеру и выравниванию каждого объекта, который он устанавливает, поэтому он знает, нуждается ли стек в заполнении, чтобы привести следующий объект к правильному выравниванию.