问题来自 rustlings ,有问题的代码如下:
fn main() { let mut x = 100; let y = &mut x; let z = &mut x; *y += 100; *z += 1000; assert_eq!(x, 1200); }
这个可以理解,因为 y, z 同时借用了 x ,2 个可变借用可能导致数据冲突。
改成如下形式可通过编译:
fn main() { let mut x = 100; let y = &mut x; *y += 100; let z = &mut x; *z += 1000; assert_eq!(x, 1200); }
不理解的地方是,y 和 z 都在同一个作用域,也就是 main 函数的作用域内仍然存在 2 个可变借用,那为什么修改后的代码却编译通过了呢?
![]() | 1 irytu 2022-03-02 13:21:41 +08:00 via iPhone ![]() 因为 y 的生命周期止于第四行 编译器是可以接受的 |
![]() | 2 noe132 2022-03-02 13:22:03 +08:00 ![]() 因为你看起来借了 2 次,实际上在任意时间只借了一次。 执行完 *y += 100; 后,编译器就知道你后面的代码不需要 y 了,所以 y 相当于不存在了。虽然你看起来 y 在整个 main 函数都还能使用,但实际上编译器想的更加细。 |
![]() | 3 IsmeOvo 2022-03-02 14:01:02 +08:00 ![]() 可以搜索关键字 Non-Lexical Lifetimes (NLL) |
![]() | 4 miyuki 2022-03-02 14:24:16 +08:00 编译器发现 y 只最多出现在第四行,后面不用了 |
![]() | 5 zhs227 2022-03-02 14:26:16 +08:00 ![]() 老版本的编译器会报错的,新版本只会检查到最后有引用的一行。也就是楼上说的 NLL 。 |
![]() | 6 chuanqirenwu OP @IsmeOvo 感谢,这下理解了。 |