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

如何用std::array替代std::unordered_map并逐个填充指定元素?

用std::array替代std::unordered_map优化枚举键值访问性能

问题背景

我原本用std::unordered_map存储枚举与纹理数据的映射,但这个map被数千次访问,性能开销占所在函数运行时间的20%。考虑到枚举值可以直接作为数组索引,想换成std::array来提升性能,但填充数组时遇到了"incomplete"错误。需要注意的是,并非所有枚举值都需要对应纹理对象,未设置的元素可以为nullptr,希望能逐个定义数组中的值。

原实现代码

Block.h

enum class BlockType : uint8_t {
    BlockType_Air = 0,
    BlockType_Default = 1,
    BlockType_Grass = 2,
    BlockCount
};

struct BlockTextureData {
    std::string top;
    std::string bottom;
    std::string left;
    std::string right;
    std::string front;
    std::string back;
};

extern std::unordered_map<BlockType, BlockTextureData*> BlockTextures;

Block.cpp

std::unordered_map<BlockType, BlockTextureData*> BlockTextures = {
    {BlockType::BlockType_Default, new BlockTextureData{"UV","UV","UV","UV","UV", "UV"}},
    {BlockType::BlockType_Grass, new BlockTextureData{"GrassTop","GrassBottom","GrassSide","GrassSide","GrassSide", "GrassSide"}}
};

错误的尝试代码

Block.h

extern std::array<BlockTextureData*, static_cast<size_t>(BlockType::BlockCount)> BlockTextures;

Block.cpp

std::array<BlockTextureData*, static_cast<size_t>(BlockType::BlockCount)> BlockTextures[static_cast<size_t>(BlockType::BlockType_Default)] = new BlockTextureData{"UV","UV","UV","UV","UV", "UV"};

std::array<BlockTextureData*, static_cast<size_t>(BlockType::BlockCount)> BlockTextures[static_cast<size_t>(BlockType::BlockType_Grass)] = new BlockTextureData{"GrassTop","GrassBottom","GrassSide","GrassSide","GrassSide", "GrassSide"};

正确的实现方式

你的错误在于重复定义了BlockTextures,并且错误地将数组当作二维数组来赋值。正确的做法是先创建一个大小为BlockCount的数组,默认初始化所有元素为nullptr,再通过枚举值转换的索引逐个赋值。

修正后的代码

Block.h

#include <array>
#include <string>

enum class BlockType : uint8_t {
    BlockType_Air = 0,
    BlockType_Default = 1,
    BlockType_Grass = 2,
    BlockCount
};

struct BlockTextureData {
    std::string top;
    std::string bottom;
    std::string left;
    std::string right;
    std::string front;
    std::string back;
};

// 声明全局数组,大小由枚举值BlockCount确定
extern std::array<BlockTextureData*, static_cast<size_t>(BlockType::BlockCount)> BlockTextures;

Block.cpp

#include "Block.h"
#include <array>

// 初始化数组,所有元素默认值为nullptr
std::array<BlockTextureData*, static_cast<size_t>(BlockType::BlockCount)> BlockTextures{};

// 初始化需要的元素,可放在初始化函数中
void initBlockTextures() {
    // 将枚举值转为size_t作为数组索引
    auto defaultIdx = static_cast<size_t>(BlockType::BlockType_Default);
    BlockTextures[defaultIdx] = new BlockTextureData{"UV","UV","UV","UV","UV", "UV"};

    auto grassIdx = static_cast<size_t>(BlockType::BlockType_Grass);
    BlockTextures[grassIdx] = new BlockTextureData{"GrassTop","GrassBottom","GrassSide","GrassSide","GrassSide", "GrassSide"};
}

// 确保初始化函数在程序启动时执行(比如用全局初始化器)
namespace {
    struct Initializer {
        Initializer() {
            initBlockTextures();
        }
    } init;
}

补充说明

  1. 内存管理:如果使用new创建BlockTextureData对象,记得在程序退出时遍历数组,对非nullptr的元素执行delete,避免内存泄漏。
  2. 访问方式:后续访问时直接用BlockTextures[static_cast<size_t>(BlockType::XXX)]即可,比unordered_map的查找快得多。

内容的提问来源于stack exchange,提问作者Marko Taht

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:18:08