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

如何将两个64位数值作为std::unordered_map的键并实现哈希?

实现两个64位数值作为std::unordered_map的键

1. 定义键类型

首先把两个64位数值封装成结构体,作为整体键使用,确保任意一个位变化都会产生不同的键:

#include <cstdint>
#include <unordered_map>

struct RenderPipelineKey {
    uint64_t renderState;
    uint64_t pipelineState;

    // 重载==运算符,用于哈希表判断键是否相等
    bool operator==(const RenderPipelineKey& other) const noexcept {
        return renderState == other.renderState && pipelineState == other.pipelineState;
    }
};

2. 实现高效哈希函数(无需循环)

以下几种方法都不需要循环16次,基于位运算或编译器内置逻辑实现高效哈希:

方法1:组合std::hash结果

利用标准库对uint64_t的哈希支持,通过移位、异或组合两个哈希值:

namespace std {
    template<> struct hash<RenderPipelineKey> {
        size_t operator()(const RenderPipelineKey& key) const noexcept {
            auto hashRender = hash<uint64_t>{}(key.renderState);
            auto hashPipeline = hash<uint64_t>{}(key.pipelineState);

            // 64位系统下直接移位异或,32位系统拆分64位值组合
            if constexpr (sizeof(size_t) == 8) {
                return hashRender ^ (hashPipeline << 32 | hashPipeline >> 32);
            } else {
                uint32_t pipeLow = static_cast<uint32_t>(key.pipelineState);
                uint32_t pipeHigh = static_cast<uint32_t>(key.pipelineState >> 32);
                return hashRender ^ (pipeLow ^ (pipeHigh << 16));
            }
        }
    };
}

方法2:使用编译器内置哈希合并函数

GCC/Clang可直接用__builtin_hash_combine,MSVC可自行实现类似逻辑,底层都是高效位运算:

namespace std {
    template<> struct hash<RenderPipelineKey> {
        size_t operator()(const RenderPipelineKey& key) const noexcept {
            size_t seed = hash<uint64_t>{}(key.renderState);
            __builtin_hash_combine(seed, key.pipelineState);
            return seed;
        }
    };
}

方法3:用std::pair简化(C++20及以上)

C++20标准库已为std::pair提供哈希特化,可直接用std::pair<uint64_t, uint64_t>作为键,省去自定义结构体:

// 直接使用pair作为键
std::unordered_map<std::pair<uint64_t, uint64_t>, YourValueType> stateMap;

3. 哈希表的使用示例

定义好键和哈希后,即可正常操作std::unordered_map:

// 假设值类型为渲染资源指针
std::unordered_map<RenderPipelineKey, RenderResource*> stateCache;

// 添加元素
RenderPipelineKey key{0x123456789ABCDEF0, 0xFEDCBA9876543210};
stateCache[key] = new RenderResource();

// 查询元素
auto it = stateCache.find(key);
if (it != stateCache.end()) {
    // 使用it->second访问对应资源
}

额外优化:用128位整数作为键

如果追求极致简洁,可将两个64位值拼接为__int128,手动实现其哈希逻辑:

namespace std {
    template<> struct hash<__int128> {
        size_t operator()(__int128 val) const noexcept {
            uint64_t low = static_cast<uint64_t>(val);
            uint64_t high = static_cast<uint64_t>(val >> 64);
            return hash<uint64_t>{}(low) ^ (hash<uint64_t>{}(high) << 1);
        }
    };
}

// 生成128位键
__int128 makeKey(uint64_t renderState, uint64_t pipelineState) {
    return (static_cast<__int128>(renderState) << 64) | pipelineState;
}

// 使用哈希表
std::unordered_map<__int128, RenderResource*> stateCache;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 07:17:11