为什么rust在引用可变变量时会重新声明可变性?
我正在阅读,一些我不懂的东西吸引了我的目光:为什么rust在引用可变变量时会重新声明可变性?,rust,Rust,我正在阅读,一些我不懂的东西吸引了我的目光: 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");
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);
}
在代码行5,它用let mut guess=String::new()
声明了一个可变变量,但在下一行read_line()
的参数也有一个mut
关键字
如果变量首先被定义为可变的,那么为什么我们要再次使用mut
,而不是像这样使用引用:
io::stdin().read_line(&guess).expect("Failed to read line");
如果为变量定义了类型,那么当我们使用引用时,默认情况下类型(
mut
)不应该存在吗 因为可以对可变变量进行不可变引用,也可以对可变变量进行可变引用。关键字mut
选择要创建的引用类型
let mut foo = 1;
example1(&foo); // May not modify `foo`
example2(&mut foo); // May modify `foo`
另见:
&
创建对某事物的引用时,默认情况下,这会创建对不可变事物的引用,至少对于引用而言,值本身是允许可变的,值的真实可变状态并不重要
当你来自所有事物都是可变的语言时,这有点违反直觉。你不需要明确地告诉别人某些东西是可变的,这是默认的行为。当我们创建某个对象时,需要显式地编写该对象的引用是不可变的,这几乎是不存在的
因此,要创建对可变内容的引用,必须显式使用
&mut
。这是一条规则,编译器知道值可以进行变异,可以为您执行,但Rust要求您显式编写它,就这么简单。TL;DR:这是一项设计决策。Rust编译器可以合理地推断出易变性是否必要;然而,对于人类读者来说,这可能并不明显
说来话长
如果你看RIST的前身,你会发现C++中引用参数的使用是不被普遍理解的。在C++中:
foo.call(bar);
只有call
的定义才能让您知道bar
是通过值、常量引用还是可变引用传递的。因此,对于任何可修改的参数,都会强制通过指针传递,以便在调用端区分变量是否可以通过调用修改,这是臭名昭著的
在设计锈迹时,有一个大的和故意强调明确性。其原因是,代码的阅读频率高于编写频率,因此语法和语义应该针对阅读和理解进行优化
明确性和简洁性之间存在紧张关系,因此明确性并不总是首选,但通常是首选
在可变引用的情况下,考虑到围绕借阅检查的规则以及可变借阅对它们的影响,首选明确性。您应该继续阅读:)“现在,您需要知道的是,与变量一样,引用在默认情况下是不可变的。因此,您需要编写
&mut guess
,而不是&guess
,以使其可变。(第4章将更全面地解释参考文献。)“是的,我读过,但我不想逃课,我每天读一页,现在不理解会打乱我的节奏。。。那个医生在那之前是如此彻底:)…前两行有什么意义?如果foo
是类型可变的,那么它不应该在整个过程循环中保持这种状态吗?也谢谢你的帮助answer@ANWfoo
的类型是i32
——可变性不是该类型的属性。example
的参数类型为&i32
,而example2
的参数类型为&mut i32
。仅仅因为某些东西是可变的,并不意味着你总是想让它变异。知道某些东西无法更改更有效。@实际上,这里计算的类型不是foo
的类型,而是example1
和example2
的参数类型。由于编译器知道example1
接受&i32
参数,而example2
接受&mut i32
,因此函数调用中的mut
对于编译器来说确实是多余的。然而,对于那些阅读代码的程序员来说,这是非常有用的,他们可以一眼就知道函数调用是否有可能改变参数。请记住,阅读的时间比编写代码的时间要多得多。