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中的值的地址,因此可以直接修改。
