为什么这三个print_max功能都会起作用?哪一种是最佳实践?是 的for number in number_list快捷方式吗for number in number_list.iter()?
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
print_max_1(&number_list);
print_max_2(&number_list);
print_max_3(&number_list);
}
fn print_max_1(number_list: &[u16]) {
let mut largest = &number_list[0]; // borrow the first number
for number in number_list.iter() { // borrowing?
if number > largest {
largest = number;
}
}
println!("The largest number is {}", largest);
}
fn print_max_2(number_list: &[u16]) {
let mut largest = &number_list[0]; // borrow the first number
for number in number_list { // shortcut for .iter()?
if number > largest {
largest = number;
}
}
println!("The largest number is {}", largest);
}
fn print_max_3(number_list: &[u16]) {
let mut largest = number_list[0]; // copying?
for &number in number_list.iter() { // borrowing?
if number > largest { // no error
largest = number;
}
}
println!("The largest number is {}", largest);
}
Run Code Online (Sandbox Code Playgroud)
为什么这不起作用?
fn print_max_4(number_list: &[u16]) {
let mut largest = &number_list[0];
for &number in number_list {
if number > largest {
largest = number;
}
}
println!("The largest number is {}", largest);
}
Run Code Online (Sandbox Code Playgroud)
错误消息显示 that largestis &u16while numberis u16。为什么不是number &u16?
让我们一一解决这些问题。
print_max_1这里,largest是一个可变变量,它保存对 a 的不可变引用u16(即它保存 a &u16)。在循环中,number也是一个&u16, 其中largest, 是从 借用的number_list。和number都larger被隐式取消引用以执行比较。如果 引用的值number大于 引用的值,则将包含在中larger的不可变引用的副本存储到中。numberlargest
print_max_2在这种情况下,由于number_list本身是借用的,因此 的分析print_max_2与 相同print_max_1。
print_max_3这里largest有一个u16。你说得对,number_list[0]是复制的,但值得注意的是,这个复制品很便宜。在循环内, 的每个元素都number_list被复制并直接存储在 中number。如果number大于largest,则将新的最大值直接存储在 中largest。这是您编写的三个实现中最优化的一个,因为您消除了引用(即指针)引入的所有不必要的间接。
print_max_4您再次存储对number_listin的第一个元素的引用largest,即largesta &u16。类似地,与 中的情况一样print_max_3,number是 a u16,它将保存 中元素的副本number_list。然而,正如您所指出的,这个函数是有问题的孩子。
在循环内,编译器会指出两个错误:
PartialOrder定义的不同类型,即largest哪个是 a&u16和number哪个是 a u16。Rust 不会尝试猜测这种比较的含义,因此为了解决这个问题,您必须使两者具有number相同largest的类型。在这种情况下,您想要做的是largest使用运算符显式取消引用,这将允许您将it 指向的内容与中包含的内容*进行比较。最终的比较看起来像
u16u16numberif number > *largest { ... }
Run Code Online (Sandbox Code Playgroud)u16在类型 的变量中&u16,这是没有意义的。不幸的是,在这里你会碰壁。在循环中,您拥有的只是从 复制的数字的值number_list,但largest需要保存对 a 的引用u16。我们不能简单地number在这里借用(例如通过编写largest = &number),因为numberwill 在循环结束时被删除(即超出范围)。唯一的解决方法是print_max_2通过存储最大值本身而不是指向它的指针来恢复到。至于是否for number in number_list是捷径for number in number_list.iter(),答案是否定的。前者将取得 的所有权number_list,并且在每次迭代期间,number取得 中下一个值的所有权number_list。相比之下,后者仅执行借位,并且在循环的每次迭代期间,number接收对 的下一个元素的不可变引用number_list。
在这种特定情况下,这两个操作看起来是相同的,因为获得不可变引用的所有权只需要制作一个副本,从而使原始所有者完好无损。有关更多信息,请参阅有关和 之间差异的相关问题的答案。.into_iter().iter()
| 归档时间: |
|
| 查看次数: |
1378 次 |
| 最近记录: |