今天的Rust之谜来自于《Rust编程语言》第一版的第4.9节。借用和引用的示例如下:
fn main() {
fn sum_vec(v: &Vec<i32>) -> i32 {
return v.iter().fold(0, |a, &b| a + b);
}
fn foo(v1: &Vec<i32>) -> i32 {
sum_vec(v1);
}
let v1 = vec![1, 2, 3];
let answer = foo(&v1);
println!("{}", answer);
}
这看起来是合理的。它打印出“6”,这是你期望的,如果sum_vec
的 v
是一个 C++ 引用,它只是一个指向内存位置的名称,与我们在main()
中定义的矢量v1
一样。
然后我用以下内容替换了sum_vec
的主体:
fn sum_vec(v: &Vec<i32>) -> i32 {
return (*v).iter().fold(0, |a, &b| a + b);
}
编译并按预期工作。好了,那不是…完全疯狂的。编译器试图让我的生活更轻松,我明白这一点。虽然令人困惑,但我必须记住它作为语言的一个特定习惯,但不是完全疯狂的。 然后我尝试了:
fn sum_vec(v: &Vec<i32>) -> i32 {
return (**v).iter().fold(0, |a, &b| a + b);
}
它还能工作!到底是怎么回事?
fn sum_vec(v: &Vec<i32>) -> i32 {
return (***v).iter().fold(0, |a, &b| a + b);
}
type [i32] cannot be dereferenced
. 意思是 "无法对 [i32] 类型进行解引用操作"。噢,谢天谢地,这听起来讲得通。但我本来希望早两轮就能搞定!
Rust 中的引用不是 C++ 中的“内存中另一个位置的名称”,那它们到底是什么呢?它们也不是指针,并且关于引用的规则似乎要么很玄学,要么非常特例化。为什么引用、指针和指向指针的指针在这里都可以同样地发挥作用呢?
let v = &vec![42]; <[_]>::iter(&**v);
。序列是:Vec 的引用、Vec、Slice、Slice 的引用。 - Josh Lee