c++ - std::variant 的 std::vector 的内存布局如何?
问题描述
我在堆栈中分配了一种类型std::vector
。std::variant
由于每个变体的大小都是可变的。我想知道向量的内存布局在堆栈中是什么。
解决方案
C++ "std:variant" 类型正在模仿良好的旧 C "union" 类型(或者,更接近地,pascal 标记记录),这意味着它们都具有相同的大小,唯一的区别是 std::variant 值有与它们相关的附加信息,此信息跟踪变体替代方案。std::variant 的确切实现是特定于平台的,恐怕是不可移植的。
std::variant 的 Visual C++ 实现非常复杂(大约 86 KB 的元模板代码)。但是我们可以通过简单的测试来猜测一些实现细节:
#include <stdio.h>
#include <cstdint>
#include <variant>
template <typename T>
void Dump(T val)
{
printf("Size %zu: Data:",sizeof(val));
for (int i = 0; i < sizeof(val); ++i) printf(" %02X", (reinterpret_cast<std::uint8_t*>(&val))[i]);
printf("\n");
}
#pragma pack(push, 1)
typedef struct { std::variant<std::uint32_t, std::uint64_t> u; } dummy_variant_t;
#pragma pack(pop)
int main(int, char*[])
{
dummy_variant_t abc;
// _______________________ __ ?? ?? ?? ?? ?? ?? ?? <-- unknown info
// Size 16: Data: EF CD AB 89 67 45 23 01 01 13 EC 00 02 00 00 00
// ^variant data ^tag(uint64_t)
abc.u = static_cast<std::uint64_t>(0x123456789ABCDEF);
Dump(abc);
// ___________ xx xx xx xx __ ?? ?? ?? ?? ?? ?? ?? <-- unknown info
// Size 16: Data: 78 56 34 12 67 45 23 01 00 13 EC 00 02 00 00 00
// ^ ^garbage ^tag(uint32_t)
// |
// +variant data
abc.u = static_cast<std::uint32_t>(0x12345678);
Dump(abc);
return 0;
}
在这里我们看到这个特定的 std::variant 类型大致对应于:
struct variant_t
{
union
{
std::uint32_t m_Variant1;
std::uint64_t m_Variant2;
}
m_VariantData;
std::uint8_t m_Tag;
std::uint8_t m_Unknown[7];
};
所以,我希望这有助于确定你的确切类型。Pascal 很久以前就有这些类型(几乎从一开始),请参阅freepascal 手册的摘录
推荐阅读
- .net - 无法提供样式字典的文件路径
- android - 尝试在谷歌助手 (android) 上安装 Plex
- python - 断言字符串上部被调用
- mysql - Symfony ulid 和 phpmyadmin
- sql-server - 数据字典中的数据项表和数据表有什么区别?
- java - 正则表达式在多行文本中获取 @ 和 @ 之间的所有内容
- android - Jetpack Compose 从我底栏中的 viewmodel 调用函数
- html - 具有相同特性的两个 CSS 声明有一个奇怪的行为
- node.js - 尝试获取用户 Youtube 频道时出现权限不足错误
- r - 错误消息 - 被视为 NA 的未替换值不兼容。请详细指定替换或提供 .default