我在阅读 Rust 库的文档时遇到了这段代码:
for (ent, pos, vel) in (&*entities, &mut pos_storage, &vel_storage).join() {
println!("Processing entity: {:?}", ent);
*pos += *vel;
}
&*entities
在这里是做什么的?从我的理解来看,它是对entities
进行取消引用,然后再次引用。但是为什么要这样做?
这是一个明确的reborrow,它是Rust中常见的惯用语。
在表达式中,&
只有一个含义:它获取类型为T
的表达式(必须是place expression),并借用其引用,类型为&T
。
对于引用,*
与&
相反--它获取一个引用(&T
)并创建一个类型为T
的place expression。但是,根据不同类型的指针,*
可能有不同的含义,因为您可以通过实现Deref
覆盖它。因为*
涉及到一些编译器魔法,会自动解引用Deref::deref
的返回值,所以您可以使用&
运算符来借用*
的结果,将其转换回普通引用。
所以,&*foo
是将“任何类型的指向T
的指针”明确地reborrows成&T
的一种方式,等同于手动调用Deref::deref(&foo)
。
(上述解释也适用于&mut
的借用--只需将&
替换为&mut
,将Deref
替换为DerefMut
。)
在您提供的示例中,不清楚entities
是什么,但它可能是某种智能指针,其中join()
方法需要一个普通引用。对于另一个需要此操作的示例,请考虑使用[&str]::concat
将String
与一些&str
连接起来:
// I want to concatenate this with some other strings
let s = String::from("Amelia");
// The following won't compile: you can't make an array of &str and String
assert_eq!(["Hello", ", ", s].concat(), "Hello, Amelia"); // WRONG
// However, &*s takes a reference to the str pointed to by s.
assert_eq!(["Hello", ", ", &*s].concat(), "Hello, Amelia"); // OK