排列成一排的结构,可诱导单个成员的规则排列

时间:2019-06-30 23:13:08

标签: arrays c++11 memory-alignment alignas struct-member-alignment

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

否则,将存在指向数组中特定成员实例的指针,这些实例将没有整数的指针距离(以成员类的大小度量)。

例如,给定以下结构:

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

一个std::vector<employee> v(或与此相关的数组employee[N]诱导一个由salary个成员(步​​幅为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>{};

,它可能最终可以工作。但这是很多手工工作,当我更改系统或添加新成员时,它可能会更改。

是否有更自动的方法?或遵循一些惯例来减轻这个问题的痛苦

0 个答案:

没有答案