何时取消引用或不取消引用

Aus*_*ile 16 pointers reference dereference rust

我正在浏览“Rust Book”网站,以便学习即将到来的工作面试的语言。在向量章节中,有两个代码示例:

fn main() {
    let v = vec![100, 32, 57];
    for i in &v {
        println!("{}", i);
    }
}
Run Code Online (Sandbox Code Playgroud)

和:

fn main() {
    let mut v = vec![100, 32, 57];
    for i in &mut v {
        *i += 50;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想知道,为什么对于第一个样本,当我们将对向量元素i的引用传递到:

println!("{}", i);

但是在我们向向量的每个元素添加 50 的示例中,在添加到 50 之前,我们必须使用 * 取消引用该元素?

我们为什么不/不能做以下事情:

fn main() {
    let v = vec![100, 32, 57];
    for i in &v {
        println!("{}", *i); // why don't we have to dereference before we pass to println!?
    }
}
Run Code Online (Sandbox Code Playgroud)

或者:

fn main() {
    let mut v = vec![100, 32, 57];
    for i in &mut v {
        i += 50; // why can't we just add directly to the reference like this?
    }
}
Run Code Online (Sandbox Code Playgroud)

我一定是误解了我读到的内容,但我认为 Rust 能够辨别何时需要取消引用或不需要自动取消引用。我想我不明白为什么我们需要在两个示例中取消引用(或不取消引用)。我提供的两个示例都用我想知道的特定代码进行了注释。

JMA*_*MAA 8

我认为最简单的看待这个问题的方法是第二个例子是“正常”的例子。

fn main() {
    let mut v = vec![100, 32, 57];
    for i in &mut v {
        *i += 50;
    }
}
Run Code Online (Sandbox Code Playgroud)

i是 a &mut i32(只是i32因为没有任何东西可以从中推断任何其他整数类型),因此要分配给它,您需要取消引用 a mut i32

这个println!例子就是做一些“魔术”的人。println!将格式化类型,无论它们是按值传递还是按引用传递。这非常方便,您不希望它(例如)克隆您想要打印的每个字符串,然后在应用程序中稍后使用。


编辑:

为了完整起见,这种“魔法”根本不是真正的魔法,而是对语言功能的良好利用。println!(与进行格式化的所有其他标准宏一样,例如panic!format!)使用标准库中的格式化机制。Display这可以与任何实现该特征(或者Debug如果使用特征的话)的类型一起使用{:?}。并为该实现的所有引用Display提供了一个全面的实现DisplayDebug也执行此操作):

impl<'_, T> Display for &'_ T where
    T: Display + ?Sized, 
{ /* ... */ }
Run Code Online (Sandbox Code Playgroud)

因此,任何可以使用值进行格式化的内容,也可以使用引用进行格式化。