1

假设我有以下简单的类:

    struct  employee{
        std::string name;
        short salary;
        std::size_t age;
        employee(std::string name, short salary, std::size_t age) : name{name}, salary{salary}, age{age}{}
    };

由于我希望对员工数组中的员工成员进行类似数组的访问name,因此我需要例如偏移量是可分割的:

    static_assert( sizeof(employee) % sizeof(std::string) == 0, "!" );

为了确保我使用的是alignas指令:

    struct alignas(sizeof(std::string)) employee{
        std::string name;
        short salary;
        std::size_t age;
        employee(std::string name, short salary, std::size_t age) : name{name}, salary{salary}, age{age}{}
    };

这似乎可以完成这项工作(现在static_assert上述通过了)。

但是,当我打开clangUB(未定义的行为清理程序)并尝试构建该对齐版本的类 clang 的数组时,检测到错误:

SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/move.h:139:31 in 
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/ext/new_allocator.h:153:10: runtime error: member call on misaligned address 0x0000022de1b0 for type 'employee', which requires 32 byte alignment
0x0000022de1b0: note: pointer points here
 00 00 00 00  c0 e1 2d 02 00 00 00 00  05 00 00 00 00 00 00 00  44 61 76 69 64 00 00 00  00 00 00 00

那么让alignment员工和name成员兼容的正确方法是什么?(所以数组的成员可以通过指针std::string*算术访问)

奖励问题:如何对齐所有成员以允许对employees 数组的所有成员进行数组访问。

有关更多详细信息,请参见此处:对齐/偏移结构的特定成员

基本上,我注意到根据 clang 有效的解决方案是 UB,我正在寻找替代方案。


通过成员的数组访问,我的意思是能够做到这一点:

employee ARRAY[2];
std::string* p = &ARRAY[0].name;
std::string& p2 = *(p + 2); // can be +3 or any necessary integer
assert( &p2 == &ARRAY[1].name );

请注意,我发现这很有效(在我的系统中),工作是否匹配步幅,而 clang 并没有说是 UB:

    struct employee{
        std::string name;
        short salary;
        std::size_t age;
        char dummy[9];
        employee() = default;
    }

这是迄今为止我发现的唯一不产生 UB 的选项。我想知道是否还有更好的方法。

最惯用的路径似乎使用alignas但它也根据clang触发UB。

    struct employee{
        std::string name alignas(32);
        short salary;
        std::size_t age;
        employee(std::string name, short salary, std::size_t age) : name{name}, salary{salary}, age{age}{}
    };
4

0 回答 0