В C ++, по крайней мере, в GCC и Clang, слишком выровненный тип, встроенный в контейнер (std :: vector), по-видимому, обрабатывается по-разному в зависимости от того, является ли тип переопределенной структурой или переопределенным перечислением , Для версии struct, элемент выровнен для каждого, в то время как для перечисляемой только общий буфер имеет указанное выравнивание.
Это поведение определено стандартом? И если да, то в какой части это упоминается? Или определяется реализацией и на нее не следует полагаться?
Обратите внимание на следующее:
#include<cstdint>
#include<iostream>
#include<vector>
struct alignas(16) byte_struct {std::uint8_t value;};
enum alignas(16) byte_enum : std::uint8_t {};
int main() {
{//with struct
std::vector<byte_struct> bytes;
bytes.push_back(byte_struct{1});
bytes.push_back(byte_struct{2});
bytes.push_back(byte_struct{3});
for(auto it = bytes.begin(); it!= bytes.end(); ++it) {
std::cout<<&*it<<std::endl;
}
}
{//with enum
std::vector<byte_enum> bytes;
bytes.push_back(byte_enum{1});
bytes.push_back(byte_enum{2});
bytes.push_back(byte_enum{3});
for(auto it = bytes.begin(); it!= bytes.end(); ++it) {
std::cout<<&*it<<std::endl;
}
}
}
Версия с перестроенной структурой печатает следующее
0x10a9ec0
0x10a9ed0
0x10a9ee0
Версия с перечеркнутым перечислением печатает следующее
0x10a9e70
0x10a9e71
0x10a9e72
В векторном хранилище каждая структура byte_struct выравнивается по 16-байтовой границе, в отличие от байта_enum, для которого выравнивание применяется только к буферу в целом, но не для каждого отдельного элемента.
Это поведение идентично в GCC 9.1 и Clang 8.0, в то время как MSVC 19.20 обнаруживает внутреннюю ошибку компилятора.
Ссылка для проводника компилятора: https://godbolt.org/z/GUg2ft