我是 Rust 的新手,我发现很难理解整个所有权/借用概念。 ...即使阅读了所有官方指南。
为什么下面的代码编译没有任何问题?
use std::io;
fn main() {
let mut input = io::stdin();
let mut lock = input.lock();
let mut lines_iter = lock.lines();
for line in lines_iter {
let ok = line.ok();
let unwrap = ok.unwrap();
let slice = unwrap.as_slice();
println!("{}", slice);
}
}
...但这不是吗?
use std::io;
fn main() {
let mut lines_iter = io::stdin().lock().lines();
for line in lines_iter {
let slice = line.ok().unwrap().as_slice();
println!("{}", slice);
}
}
从我天真的观点来看,两个代码示例的作用完全相同。唯一的区别是第一个使用一些中间变量,而第二个是链接函数调用。
在编译第二个的时候,它对我大吼大叫
- error: borrowed value does not live long enough
- note: reference must be valid for the block at
- note:...but borrowed value is only valid for the statement
- help: consider using a `let` binding to increase its lifetime
但老实说,我不知道编译器试图告诉我什么。 我所了解的是我有一个终生的问题。但为什么?
两个代码示例之间有什么区别?为什么以及如何影响什么的生命周期?
最佳答案
定义中间变量可以延长中间值的生命周期。临时值(例如 io::stdin()
和 io::stdin().lock()
中的 io::stdin().lock().lines()
)在语句末尾不再存在,除非它们被移动(即 io::stdin().lock()
的情况)。
在let mut lines_iter = io::stdin().lock().lines();
:
-
io::stdin()
返回一个新的Stdin
-
.lock()
返回一个新的StdinLock<'a>
(它引用了Stdin
;您在文档中看不到<'a>
,因为生命周期在源代码中是 elided) -
.lines()
返回一个新的Lines<StdinLock<'a>>
(取得锁的所有权)。
.lock()
返回类型的生命周期参数表明锁是从 Stdin
借用的目的。当您从某个对象借用时,该对象必须至少存活到借用的时间。但是,您试图让一个变量持续到函数结束,但它借用了一个将在语句结束时删除的对象(因为 io::stdin()
是一个临时值)。
历史记录:最初提出此问题时,.lines()
会借锁。现在,.lines()
取而代之的是锁的所有权。这意味着现在,只有 io::stdin()
需要绑定(bind)到一个变量;不再需要绑定(bind) input.lock()
的结果.
关于compiler-errors - 链接函数调用与使用中间变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27468558/