Nee*_*ahn 8 c++ memory-alignment language-lawyer c++17
在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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
具有过度对齐的结构的版本将打印以下内容
0x10a9ec0 0x10a9ed0 0x10a9ee0
带有过度对齐的枚举的版本将打印以下内容
0x10a9e70 0x10a9e71 0x10a9e72
在向量存储区中,每个byte_struct都对齐到16个字节的边界,而byte_enum的对齐方式只适用于整个缓冲区,而不适用于每个单独的元素。
在GCC 9.1和Clang 8.0上,此行为相同,而MSVC 19.20遇到内部编译器错误。
编译器资源管理器的链接为:https : //godbolt.org/z/GUg2ft
这是C ++核心工作组问题2354,最近已通过删除应用alignas到enum类型的权限来解决。(在撰写本文时,问题列表的最新公共版本不包含解决方案,但您可以在P1359R0中找到该解决方案,该解决方案已于2019年2月被C ++工作草案采纳并被接受为缺陷报告(表示该修复程序旨在追溯应用)。
问题在于我们有两个相互矛盾的要求:
一个枚举基(包括隐式枚举基的int在一个范围的列举)指定枚举的基本类型,枚举需要具有相同的对象表示(包括sizeof所有值的表示)作为其基本的类型,和
一个对准说明符指定的类型,这反过来也必须限制的对准sizeof(E)(这是通过定义类型的两个对象之间的距离E在一个阵列),以所述对准的倍数。
您不能同时拥有两者,因此我们通过消除在枚举类型上指定对齐方式的能力来解决了冲突。
最好的建议是不要将对齐说明符应用于枚举类型。实施将在某个时候停止接受这一点。(不过,可以在变量或非静态数据成员的声明中将对齐方式应用于类型的使用)。