fn main() {
let mut m = 12;
{
let n = &mut m;
*n = 13;
{
let k = n;
*k = 20;
println!("{}", k);
} // k's scope ends here, right?
println!("{}", n);
}
println!("{}", m);
}
Run Code Online (Sandbox Code Playgroud)
这是我运行代码时得到的:
src/main.rs:11:18: 11:19 error: use of moved value: `n` [E0382]
src/main.rs:11 println!("{}", n);
^
Run Code Online (Sandbox Code Playgroud)
但变量k的范围尚未结束吗?为什么不将所有权归还给变量n?
但变量k是否已结束其范围呢?为什么不将所有权归还给变量n?
是的,k范围已经结束,但为什么你认为它应该归还所有权?
在Rust中没有任何东西可以"归还所有权".如果某个类型没有实现Copy(并且&mut绝对没有引用),则只能移动其值.移动意味着所有权转移,因此由所有权的接收者决定如何处理该值.因此,当k超出范围时,指针被有效地"销毁"(指针本身,而不是值).由于它被移出n,绑定实际上变得未初始化,因此您得到此错误.
&mut引用是唯一的,虽然它们不可复制,因此只能移动,有时它们会自动重新扩展,也就是说,编译器会自动&mut *p为您插入.我不记得应用自动重新借用时的确切规则(据我记得,当可变引用传递给函数时可能发生这种情况,可能还有其他地方),但这不是这种情况.要使代码正常工作,您需要明确地重新借用该值:
fn main() {
let mut m = 12;
{
let n = &mut m;
*n = 13;
{
let k = &mut *n; // explicit referencing of the dereferenced value
*k = 20;
println!("{}", k);
}
println!("{}", n);
}
println!("{}", m);
}
Run Code Online (Sandbox Code Playgroud)
这样编译器知道n没有移入k并允许您在k范围结束后使用它.
正如旁注,以下(感谢Veedrac的提醒)也可以再次使用,因为自动重新生成:
fn main() {
let mut m = 12;
{
let n = &mut m;
*n = 13;
{
let k: &mut _ = n; // automatic reborrowing because of type annotation
*k = 20;
println!("{}", k);
}
println!("{}", n);
}
println!("{}", m);
}
Run Code Online (Sandbox Code Playgroud)
看来,如果编译器知道目标类型是可变引用,它将重新借用原始引用,否则,即,如果目标类型是未知的(例如,在通用上下文中或在没有显式类型注释的情况下分配给绑定时) ,引用被移动,而不是重新借用.所以是的,围绕可变引用的行为可能会有些混乱.
| 归档时间: |
|
| 查看次数: |
114 次 |
| 最近记录: |