You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中如何将大型稀疏枚举类映射到数组索引?

针对稀疏枚举类的快速查找方案

下面提供几种可行的方案,既能避免稀疏枚举直接映射带来的内存浪费,又能实现快速查找:

方案1:使用哈希表(std::unordered_map)

直接用枚举值作为键,PeopleInfo作为值存储,内存仅占用实际存在的枚举成员对应的对象空间,平均查找时间为O(1)。

#include <unordered_map>
#include <stdexcept>
#include <string>

enum class People {
    American_start = 0x0,
    John,
    Aaron,
    Asian_start = 0x10000,
    Yen_Huan,
    Kang_Hsuan,
    European_start = 0x20000,
    // 其他枚举成员
};

struct PeopleInfo {
    // 根据需求定义成员,比如姓名、地区等
    std::string name;
};

// 初始化哈希表,绑定枚举值与对应信息
std::unordered_map<People, PeopleInfo> people_map = {
    {People::John, {"John"}},
    {People::Aaron, {"Aaron"}},
    {People::Yen_Huan, {"Yen Huan"}},
    {People::Kang_Hsuan, {"Kang Hsuan"}},
    // 其他枚举成员的映射关系
};

PeopleInfo fetch(People e) {
    auto iter = people_map.find(e);
    if (iter != people_map.end()) {
        return iter->second;
    }
    // 处理无效枚举值的情况,可根据需求返回默认值或抛出异常
    throw std::invalid_argument("Invalid People enum value");
}

优缺点:实现简单,无需手动维护索引;但哈希表存在一定的运行时开销,且内存占用略大于紧凑数组。


方案2:枚举值→索引映射 + 紧凑数组

先给每个枚举成员分配连续的索引,通过哈希表将枚举值转换为索引,再用索引访问大小等于枚举成员总数的紧凑数组。

#include <unordered_map>
#include <array>
#include <stdexcept>
#include <string>

enum class People {
    American_start = 0x0,
    John,
    Aaron,
    Asian_start = 0x10000,
    Yen_Huan,
    Kang_Hsuan,
    European_start = 0x20000,
    // 其他枚举成员
};

struct PeopleInfo {
    std::string name;
};

// 枚举值到紧凑数组索引的映射
const std::unordered_map<People, size_t> enum_to_index = {
    {People::John, 0},
    {People::Aaron, 1},
    {People::Yen_Huan, 2},
    {People::Kang_Hsuan, 3},
    // 按顺序为每个枚举成员分配唯一索引
};

// 紧凑数组,大小等于实际枚举成员的数量
const std::array<PeopleInfo, 4> people_arr = {
    {"John"},
    {"Aaron"},
    {"Yen Huan"},
    {"Kang Hsuan"},
    // 数组元素顺序需与enum_to_index的索引严格对应
};

PeopleInfo fetch(People e) {
    auto iter = enum_to_index.find(e);
    if (iter != enum_to_index.end()) {
        return people_arr[iter->second];
    }
    throw std::invalid_argument("Invalid People enum value");
}

优缺点:数组访问是纯O(1)操作,比哈希表更快;但需要手动维护索引与数组元素的对应关系,新增枚举成员时要同步更新两处内容。


方案3:编译期生成映射表(C++17及以上)

利用C++编译期特性,提前生成枚举值到索引的映射和紧凑数组,运行时通过switch(编译器会优化为跳转表)实现无额外开销的快速查找,完全避免内存浪费。

#include <array>
#include <tuple>
#include <stdexcept>
#include <utility>
#include <string>

enum class People {
    American_start = 0x0,
    John,
    Aaron,
    Asian_start = 0x10000,
    Yen_Huan,
    Kang_Hsuan,
    European_start = 0x20000,
    // 其他枚举成员
};

struct PeopleInfo {
    std::string name;
};

// 编译期存储枚举值与对应信息的列表
constexpr auto people_list = std::make_tuple(
    std::pair{People::John, PeopleInfo{"John"}},
    std::pair{People::Aaron, PeopleInfo{"Aaron"}},
    std::pair{People::Yen_Huan, PeopleInfo{"Yen Huan"}},
    std::pair{People::Kang_Hsuan, PeopleInfo{"Kang Hsuan"}}
    // 新增枚举成员时仅需在此处添加
);

// 编译期获取枚举值对应的数组索引
template<People E, size_t Index = 0>
constexpr size_t get_enum_index() {
    if constexpr (Index == std::tuple_size_v<decltype(people_list)>) {
        return static_cast<size_t>(-1); // 标记为无效索引
    } else if constexpr (std::get<0>(std::get<Index>(people_list)) == E) {
        return Index;
    } else {
        return get_enum_index<E, Index + 1>();
    }
}

// 编译期生成紧凑数组
constexpr std::array<PeopleInfo, std::tuple_size_v<decltype(people_list)>> people_arr = [](){
    std::array<PeopleInfo, std::tuple_size_v<decltype(people_list)>> arr{};
    auto fill_array = [&]<size_t... Indices>(std::index_sequence<Indices...>) {
        ((arr[Indices] = std::get<1>(std::get<Indices>(people_list))), ...);
    };
    fill_array(std::make_index_sequence<std::tuple_size_v<decltype(people_list)>>{});
    return arr;
}();

PeopleInfo fetch(People e) {
    switch(e) {
        case People::John: return people_arr[get_enum_index<People::John>()];
        case People::Aaron: return people_arr[get_enum_index<People::Aaron>()];
        case People::Yen_Huan: return people_arr[get_enum_index<People::Yen_Huan>()];
        case People::Kang_Hsuan: return people_arr[get_enum_index<People::Kang_Hsuan>()];
        // 新增枚举成员时同步添加case
        default: throw std::invalid_argument("Invalid People enum value");
    }
}

优缺点:运行时查找开销极小(接近直接数组访问),内存占用最优;但需要C++17及以上支持,代码复杂度稍高。


内容的提问来源于stack exchange,提问作者Shih-Chan Huang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 11:55:27