0

我在堆栈中分配了一种类型std::vectorstd::variant由于每个变体的大小都是可变的。我想知道向量的内存布局在堆栈中是什么。

4

1 回答 1

0

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 手册的摘录

于 2021-10-28T17:50:59.410 回答