微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何正确打包这个数据结构

如何解决如何正确打包这个数据结构

我正在尝试为 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 举报,一经查实,本站将立刻删除。