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 能够辨别何时需要取消引用或不需要自动取消引用。我想我不明白为什么我们需要在两个示例中取消引用(或不取消引用)。我提供的两个示例都用我想知道的特定代码进行了注释。
我认为最简单的看待这个问题的方法是第二个例子是“正常”的例子。
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提供了一个全面的实现Display(Debug也执行此操作):
impl<'_, T> Display for &'_ T where
T: Display + ?Sized,
{ /* ... */ }
Run Code Online (Sandbox Code Playgroud)
因此,任何可以使用值进行格式化的内容,也可以使用引用进行格式化。