“&*”在Rust中的作用是什么?

11

我在阅读 Rust 库的文档时遇到了这段代码:

for (ent, pos, vel) in (&*entities, &mut pos_storage, &vel_storage).join() {
    println!("Processing entity: {:?}", ent);
    *pos += *vel;
}

&*entities在这里是做什么的?从我的理解来看,它是对entities进行取消引用,然后再次引用。但是为什么要这样做?

1个回答

12

这是一个明确的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]::concatString与一些&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

参见


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接