Rust中的一些细枝末节
Rust中的&解引用。
let v3 = Some('a');
match v3.as_ref() {
Some(&c) => {
let addr = std::ptr::addr_of!(c);
println!("addr of c: {:?}", addr);
println!("addr of v3: {:?}", ptr::addr_of!(v3));
}
None => {}
}
let v5: Option<i32> = Some(10);
match v5.as_ref() {
Some(c) => {
let addr = std::ptr::addr_of!(c);
println!("addr of c: {:?}", addr);
println!("addr of v4: {:?}", ptr::addr_of!(v5));
}
_ => {}
}
let v4 = Some(10);
match v4.as_mut() {
Some(&mut c) => {
c=20;//编译失败,报错:无法对C的值赋值两次
}
_ => {}
}
代码如上,v3和v5都能编译通过,但打印的值却不同。
v3中 解引用出来的变量c和v3的地址不是同一个,v5中c的值和v5的地址是同一个。在v3中Some(&c),做了两件事,一:解引用,使用Some(&c)匹配v3.as_ref()。二:将v3中的值赋值到变量c中,因为char类型实现了Copy trait,因此可以直接赋值,这也就导致了c和v3的地址不是同一个(因为发生了拷贝)。而v5中的c就代表了&i32,只是将i32的引用进行了赋值,因此他们指向的地址还是同一个。
v4中编译失败,理解了v3中赋值的问题不难理解。Some(&mut c)实现了解引用和赋值,但赋值后的c和v4中的值已经不是一个地址了,因此在编译层面直接就不通过(不符合可变性规则)。重新分析v4的逻辑不难发现,无非就是要修改v4中的值,此时就可以直接Some(c), 此时的c的类型为v4值的可变引用(&mut i32),指向了v4中的值的地址,因此可以直接修改。

浙公网安备 33010602011771号