为什么 rust 在引用可变变量时重新声明可变性?

sam*_*ayo 3 rust

我正在阅读The Rust Programming Language 的第二章,我不明白的东西在这里引起了我的注意:

use std::io;

fn main() {
    println!("Guess the number!");

    println!("Please input your guess.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Failed to read line");

    println!("You guessed: {}", guess);
}
Run Code Online (Sandbox Code Playgroud)

在代码第 5 行,它用 声明了一个可变变量let mut guess = String::new(),但在下一行,for 的参数read_line()也有一个mut关键字。

如果变量首先被定义为可变的,那么为什么我们mut再次使用而不是像这样只使用引用:

io::stdin().read_line(&guess).expect("Failed to read line");
Run Code Online (Sandbox Code Playgroud)

如果为变量定义了类型,那么当我们使用引用时,类型( mut)不应该默认存在吗?

She*_*ter 5

因为您可以拥有对可变变量的不可变引用或对可变变量的可变引用。关键字mut选择您要创建的参考类型。

let mut foo = 1;
example1(&foo);     // May not modify `foo`
example2(&mut foo); // May modify `foo`
Run Code Online (Sandbox Code Playgroud)

也可以看看:

  • @ANW 实际上这里重要的类型不是`foo`的类型,而是`example1`和`example2`的参数类型。由于编译器知道`example1`接受一个`&i32`参数,而`example2`接受一个`&mut i32`,函数调用中的`mut`对于编译器来说确实是多余的**。然而,它对阅读代码的程序员很有用**,他们可以一目了然地知道函数调用是否有改变参数的风险。请记住,您花在阅读上的时间比编写代码要多得多。 (2认同)

Mat*_* M. 5

TL;DR:这是一个设计决定。Rust 编译器可以合理地推断是否需要可变性;然而,对于人类读者来说,这可能并不明显。


很长的故事

如果您查看 Rust 的前辈,您会发现在 C++ 中使用引用参数并没有得到普遍赞赏。在 C++ 中:

foo.call(bar);
Run Code Online (Sandbox Code Playgroud)

只有 的定义call会让您知道bar是按值传递、常量引用还是可变引用。因此,谷歌风格指南因强制任何可修改参数传递指针而臭名昭著,以便在调用端区分变量是否可以被调用修改。

在设计 Rust 时,有大量且刻意的强调明确性。原因是代码的阅读次数比编写次数多,因此应优化语法和语义以进行阅读和理解。

明确性和简洁性之间存在张力,因此明确性并不总是首选,但通常是。

在可变引用的情况下,考虑到有关借用检查的规则以及可变借用对它们的影响,明确性是首选。