0

如果我有一个结构(例如employee下面),只有当结构的大小是所有成员大小的(最小)公倍数(LCM)时,这种结构的数组才会引发结构的所有成员的跨步数组。

否则,将有指向数组中特定成员实例的指针,它们没有整数指针距离(以成员类的大小衡量)。

因此,例如,给定这个结构:

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

A std::vector<employee> v(或employee[N]就此而言的数组)诱导成员的跨步数组salary(使用 stride sizeof(employee)/sizeof(short))以及 的跨步数组age

也就是说,工资数组是由 随机访问的&(v.data()->salary) + sizeof(employee)/sizeof(short)* n

但是,它不会引起名称的跨步数组,因为sizeof(employee)(=48) 不是sizeof(std::string)(32) 的倍数(在我的系统中)。

当然,我可以以其他方式定义结构以允许这样做:

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

我想知道找到这个正确的alignas论点是否是实现这一目标的唯一方法。此外,如果有一种自动获取该数字的方法,而无需手动查找公倍数。

我似乎没有反思的最一般的方法是做这样的事情:

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

也就是说,我必须提前枚举所有成员。我可以constexpr std::lcm通过链接它多次使用)。

这是正确的方法吗?

此外,人们总是可以找到这种甚至不起作用的病态情况,因为存在额外的限制,即对齐需要是 2 的幂(在某些系统中)。在这种情况下,公倍数也需要是 2 的幂,并且可以是一个巨大的数字:

using password_type = std::array<char, 103>; // suppose I cannot change the 103

struct alignas(std::lcm(std::lcm(std::lcm(sizeof(std::string), sizeof(short)), sizeof(std::size_t)), sizeof(password_type))) employee{ // bad alignment
    password_type password;
    std::string name;
    short salary;
    std::size_t age;
    employee(short salary, std::size_t age) : salary{salary}, age{age}{}
};

...error: requested alignment ‘3296’ is not a positive power of 2

为了使对齐 LCM 起作用,我必须手动更改特定成员的对齐方式或将constexpr上限添加到最接近的 2 次幂。

struct alignas(std::lcm(std::lcm(std::lcm(sizeof(std::string), sizeof(short)), sizeof(std::size_t)), 128)) employee{ // bad alignment
    alignas(128) password_type password;
    std::string name;
    short salary;
    std::size_t age;
    employee(short salary, std::size_t age) : salary{salary}, age{age}{}
};

但是,这仍然不能解决问题,因为alignas它不是 的一部分password_type,似乎唯一的解决方案是拥有一个std::array也需要内部对齐参数的版本!std::aligned_array<char, 103, 128>.

好的,我仍然可以这样做,但代价是修改employee最初未耦合的其他类。

struct alignas(128) password_type : std::array<char, 103>{};

它可能最终会起作用。但这需要大量的手动工作,并且可能会在我更改系统或添加新成员等时更改。

有没有更自动的方法来做到这一点?或遵循一些约定以使这个问题不那么痛苦

4

0 回答 0