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

Rust引用未实现Eq/Hash,如何将其作为基于指针相等的HashMap键?

基于指针相等的引用作为HashMap键的实现方案

核心思路

Rust标准库对引用类型&T的Eq和Hash实现默认会代理到底层T类型的对应实现,因此会基于对象内容做相等性判定,不符合你的需求。我们可以自定义一个引用包装类型,手动实现Eq和Hash,逻辑完全基于指针的内存地址:

完整实现代码

use std::hash::{Hash, Hasher};
use std::collections::HashMap;
use std::ptr;

// 自定义引用包装类,基于指针地址判等
#[derive(Copy, Clone, Debug)]
struct ByAddress<'a, T>(&'a T);

impl<'a, T> PartialEq for ByAddress<'a, T> {
    fn eq(&self, other: &Self) -> bool {
        // 直接比较两个指针是否指向同一个内存地址
        ptr::eq(self.0, other.0)
    }
}

impl<'a, T> Eq for ByAddress<'a, T> {}

impl<'a, T> Hash for ByAddress<'a, T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        // 对指针地址做哈希,而非对象内容
        (self.0 as *const T).hash(state);
    }
}

// 使用示例
struct SomeKey();
struct SomeValue();

fn main() {
    let mut m = HashMap::new();
    
    let t1 = SomeKey();
    let t2 = SomeKey();
    
    // 插入t1的引用
    m.insert(ByAddress(&t1), SomeValue());
    
    // 用同一块内存的引用查找,命中
    assert!(m.get(&ByAddress(&t1)).is_some());
    // 用不同内存的同结构对象查找,不命中
    assert!(m.get(&ByAddress(&t2)).is_none());
}

注意事项

  • 包装类型ByAddress的生命周期和原始引用绑定,借用检查会自动保证HashMap不会持有悬垂引用,所有插入的键指向的对象都必须比HashMap存活更久。
  • 如果你的场景中使用的是Box<T>、Rc<T>等智能指针,只需要修改包装逻辑取内部指针地址即可,整体实现思路一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:36:04