Hash 如何对rust中的单元结构进行“哈希”?
我想实现一种可以唯一标识的东西,此外,它不包含其他字段。它有点像ruby中的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 }
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”很好)。