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

为什么所有这些元组的大小不一样

如何解决为什么所有这些元组的大小不一样

我对有“洞”的元组感兴趣。这些孔是一个空结构。所有孔都具有相同的类型,此处称为 Empty

为了说明目的,让

struct DByte {
    std::array<std::byte,2> data;
};

struct Empty {
};

。正如我所料,

sizeof(std::tuple<DByte,Empty,Empty>) = 2

。然而,

sizeof(std::tuple<Empty,DByte,Empty>) = 3
sizeof(std::tuple<Empty,DByte>) = 3

我不明白为什么最后两种类型的大小不是 2(在带有 sizeof(std::byte) == 1 && alignof(std::byte) == 1 的平台上)。

This demonstration 还会打印这些类型在 Clang 和 GCC 下的内存布局。

为什么所有这些元组的大小与以下布局不同:

0       1       2
|     DByte     |
| Empty | Empty |

解决方法

为什么所有这些元组的大小与以下布局不同:

因为 std::tuple 的实现不会根据所包含对象的类型对其子对象重新排序(尽管它们不需要这样做)。它们使用一种取决于参数顺序的顺序,但不取决于这些参数的类型。

正常情况下,标准要求所有的子对象都有一个唯一的地址,一个标准布局类的子对象之间不能有重叠。对于空基类有一个例外1,它不需要具有唯一的地址,并且该特殊规则是某些 std::tuple 实现利用使空子对象使用 no记忆。但只有当子对象的顺序正确才能应用异常时,它才有效。

1 C++20 增加了另一个例外,但标准库在 C++11 中实现了 std::tuple,并且在不破坏 ABI 的情况下实际上不能改变它们的布局,所以这对std::tuple 的实现。如果不重新排序子对象,C++20 特性也不会改进优化。

,

为什么所有这些元组的大小与以下布局不同:

他们可能有,这只是优化失误。

您可能会在常规课程中看到同样的错过:

struct A
{
    [[no_unique_address]]DByte m;
    [[no_unique_address]]Empty e1;
    [[no_unique_address]]Empty e2;
};

struct B
{
    [[no_unique_address]]Empty e1;
    [[no_unique_address]]DByte m;
    [[no_unique_address]]Empty e2;
};

struct C
{
    [[no_unique_address]]Empty e1;
    [[no_unique_address]]Empty e2;
    [[no_unique_address]]DByte m;
};

Demo

请注意,msvc 为不同的元组 Demo 提供相同的大小。 (总是 4,所以没有空类优化)。

未指定元组的布局。所以所有这些都是可能的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。