Hash 如何对rust中的单元结构进行“哈希”?

Hash 如何对rust中的单元结构进行“哈希”?,hash,equality,rust,Hash,Equality,Rust,我想实现一种可以唯一标识的东西,此外,它不包含其他字段。它有点像ruby中的BasicObject,或者java中的Object 我添加了一个PartialEqtrait struct Thing; impl PartialEq for Thing { fn eq(&self, other: &Thing) -> bool { unsafe { self as *const Thing == other as *const Thing }

我想实现一种可以唯一标识的东西,此外,它不包含其他字段。它有点像ruby中的
BasicObject
,或者java中的
Object

我添加了一个
PartialEq
trait

struct Thing;
impl PartialEq for Thing {
  fn eq(&self, other: &Thing) -> bool {
    unsafe {
      self as *const Thing == other as *const Thing
    }
  }
}

现在,我想允许它可以被散列,问题是如何为一个没有文件的单元结构实现trait?或者,我是否应该向其添加某种类型的
对象\u id

您不能依靠指针地址来确定Rust中单元结构的唯一性,例如,以下代码将打印相同地址的两倍:

struct Foo;

fn main() {
    let x = Foo;
    let y = Foo;
    println!("{}", &x as *const _);
    println!("{}", &y as *const _);
}
您需要让它们在内存中至少占用一个字节,例如,给它们一个您从未使用过的字段:

struct Thing {
    x: u8;
}

impl Thing {
    fn new() -> Thing {
        Thing { x: 0u8 }
    }
}
然后,一个简单的方法是继续沿着您要走的同一条轨道,并使用内存中对象的地址作为散列的基值:

use std::hash::{hash,Hash};
use std::hash::sip::SipState;

struct Thing;

impl Hash for Thing {
    fn hash(&self, state: &mut SipState) {
        let addr = self as *const Thing as u64;
        addr.hash(state);
    }
}

fn main() {
    let f = Thing;
    println!("{}", hash(&f));
}

注意:将
&Thing
强制转换为
*const Thing
(然后转换为
u64
)并不不安全,因此在PartialEq的实现中不需要
不安全{}
块。

您计划如何在此处使用
Thing
?你确实需要一些数据,除非你总是想每次都返回相同的散列。@Dogbert我只想创建一些可以唯一标识自己的东西。如果创建一个
a
对象的实例,然后创建
b
,然后创建
c
,依此类推,那么
a
不应等于
对象的任何其他实例,除了它本身。如果这可以实现,我认为它也应该使用它的标识进行散列。在Rust中依赖对象标识(即它的内存位置)是非常奇怪的,因为在堆栈上移动它会改变位置。例如,随机初始化或通过全局初始化的对象id字段会更好。“单元结构不是通过Rust实例化并存储在内存中的,在这种状态下,所有实例都是相等的”,这不是真的,单元结构。(也就是说……由于它们的大小为零,它们很容易以意外的方式运行,因此最好不要依赖它。)@dbaupp是的,但如果在同一范围内实例化一个实例两次,它们将具有相同的地址……这是真的,但这只是一个实现细节,编译器完全可以为它们提供不同的地址(也就是说,您的新措辞“cannotreland”很好)。