如何解决如何正确打包这个数据结构
我正在尝试为 std::vector 创建一个自定义替换,我知道在绝大多数情况下,大小将
我在 Linux 和 Windows (gcc & msvc) 上使用 64 位编译器和 c++17。已知 int 是 32 位的。如果我们需要支持不同的东西,我会重新访问代码。
我基本上喜欢这种内存结构:
class SmallIntVector
{
int m_size;
union
{
int m_data[3]; // Used when m_size <=3
int* m_dataDynamic; // Used when m_size >=4
};
};
然而,由于对齐,这个的大小是24。我可以这样做:
class SmallIntVector
{
int m_size;
int m_data0; // first data member for m_size <= 3. Return &m_data0 and treat it as data[3].
union
{
int m_data12[2]; // next two data members.
int* m_dataDynamic; // Used with m_size>=4
};
};
但是,由于内存混叠,我很确定这是 UB。我也可以这样做:
struct ForStatic
{
int m_size;
int m_data[3];
};
struct ForDynamic
{
int m_unused; // Don't use this to avoid punning.
int *m_dataDynamic; // Pointer,must be at an 8 byte offset
};
class SmallIntVector
{
union
{
ForStatic m_stat; // When m_stat.m_size is <=3,use m_stat.m_data.
ForDynamic m_dyn; // When m_stat.m_size is >=4,use m_dyn.m_data.
};
};
大小为 16,但我认为这是对联合的非法双关语:我将使用 ForStatic 中的 m_size,同时使用 ForDynamic 中的 m_dataDynamic。
我可以通过使用 std::memcpy 读取动态指针来轻松避免 UB,但这些都感觉不对。有什么方法可以获得我正在寻找的对齐方式并避免 UB?
我省略了所有成员函数——我认为一旦结构正确,它们就很明显了。
解决方法
我建议如下:
struct ForStatic
{
int m_size; //this must be first - overlapped in union
int m_data[3];
};
struct ForDynamic
{
int m_size; //this must be first - overlapped in union
int *m_dataDynamic;
};
class SmallIntVector
{
union
{
max_align_t dummy; // ensures alignment
int m_size;
ForStatic m_stat; // When m_size is <=3,use m_stat.m_data.
ForDynamic m_dyn; // When m_size is >=4,use m_dyn.m_data.
};
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。