gpt4 book ai didi

c++ - C++ 中容器内过度对齐的结构和枚举之间的差异

转载 作者:可可西里 更新时间:2023-11-01 17:39:53 25 4
gpt4 key购买 nike

在 C++ 中,至少在 GCC 和 Clang 上,嵌入在容器中的过度对齐类型 (std::vector) 似乎根据类型是过度对齐的结构还是过度对齐的枚举而被区别对待.对于结构版本,每个元素都对齐,而对于枚举版本,只有整个缓冲区具有指定的对齐方式。标准是否指定了此行为?如果是这样,哪一部分提到了它?还是实现定义的,不应依赖?

考虑以下几点:

#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

在 vector 存储中,每个 byte_struct 都对齐到 16 字节边界,这与 byte_enum 不同,byte_enum 的对齐仅适用于整个缓冲区,而不适用于每个单独的元素。

此行为在 GCC 9.1 和 Clang 8.0 上是相同的,而 MSVC 19.20 遇到内部编译器错误。

编译器资源管理器的链接是:https://godbolt.org/z/GUg2ft

最佳答案

这是 C++ core working group issue 2354 ,最近通过删除将 alignas 应用于 enum 类型的权限解决了这个问题。 (在撰写本文时,最新的问题列表公开版本不包含该解决方案,但您可以在 P1359R0 中找到该解决方案,该解决方案于 2019 年 2 月被纳入 C++ 工作草案并被接受为缺陷报告(这意味着修复旨在追溯应用)。

问题是我们有两个相互矛盾的需求:

  1. enum-base(包括作用域枚举中 int 的隐式 enum-base)指定底层类型枚举,并且枚举需要具有与其底层类型相同的对象表示(包括 sizeof 和所有值的表示),并且

  2. alignment-specifier 指定类型的对齐方式,这反过来也必须约束 sizeof(E)(根据定义,它是两个之间的距离数组中 E 类型的对象)到所述对齐的倍数。

您不能同时拥有两者,因此我们通过删除在枚举类型上指定对齐方式的功能来解决冲突。

最好的建议是不要将对齐说明符应用于枚举类型;实现将在某个时候停止接受它。 (不过,将对齐应用于变量或非静态数据成员声明中类型的使用是可以的。)

关于c++ - C++ 中容器内过度对齐的结构和枚举之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56760874/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com