Rust中引用规则为
对于两个不同的引用而言,不可变引用实现了Copy
,可变引用没有实现。
let mut a =1;
let b=&mut a;
let c=b; //let c:&mut i32=b
println!("{}", b);
上面的代码会报错,原因是由于可变引用b是move
的,所以第三行会转移所有权到c,因此无法通过编译。
但是倘若把第三行改为let c:&mut i32=b
,代码就可以正常运行,这里发生了reborrow。
let c:&mut i32=b
等价于更具体的let c:&mut i32=&mut (*b)
。
上述代码也可以改为let c:&i32=b
,这里发生了reborrow和类型的coercion,由于存在&mut T到&T的coercion,因此代码可以正常运行。
reborrow与原引用的规则与引用和被引用对象的规则相似。
reborrow不仅在上述的例子中存在,在函数调用,结构创建等地方都会存在,由此可知当接收变量有明确的引用类型时会发生reborrow。
struct A<'a>(&'a mut i32);
let mut a =1;
let b=&mut a;
let c = A(b);
println!("{}", b);
综上所述,上述代码可以正常运行。
但是这里更改代码,将第一行A的定义改为struct A<T>(T)
,这里就会发生b的move行为,编译失败。
对元祖以及复合结构体的引用的成员取引用也是reborrow的一种。
struct A(i32,i32);
impl A {
fn foo(&mut self) {
let a=&self.0;
self.bar();
a;
}
fn bar(&mut self) {}
}
上述代码会报错。