对于空类型的变体,为什么 std::variant 实现需要超过 1 个字节?

NoS*_*tAl 8 c++ c++20 std-variant

这主要是琐碎的问题,因为我怀疑我是否需要节省空间。

在玩Godbolt 时,我注意到 libstdc++ 和 libc++ 的实现都std::variant需要超过 1 个字节来存储空结构的变体。

libstc++ 使用 2 个字节

libc++ 使用 8 个字节

我认为优化这个是不值得的,但我想知道是否还有其他原因。特别是在标准措辞中是否std::variant有阻止这种优化的东西。

Nic*_*las 9

每个对象至少占用 1 个字节的空间。计数器本身至少需要占用 1 个字节,但您还需要为对象的潜在选择空间。即使您使用 a union,它仍然需要是一个字节。并且它不能与计数器的字节相同。

现在,您可能认为这no_unique_address可以union解决问题,如果所有union元素都为空,则允许成员与计数器重叠。但请考虑以下代码:

empty_type e{};
variant<empty_type> ve{in_place_index<0>}; //variant now stores the empty type.
auto *pve = ve.get_if<0>(); //Pointer to an `empty_type`.
memcpy(pve, &e, sizeof(empty_type)); //Copying from one trivial object to another.
Run Code Online (Sandbox Code Playgroud)

该标准并未说明变体的成员是其内部成员或其任何内部成员的“潜在重叠子对象variant。因此,用户可以 100% 地memcpy从一个微不足道的空对象到另一个。

如果计数器与其重叠,它将覆盖计数器。因此,它不能与它重叠。

  • 我不知道 `std::variant` 的所有类型都必须是 `trivially_copyable`。很好的观点。 (2认同)