链接函数调用vs使用中间变量

for*_*emo 4 compiler-errors lifetime rust

我是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

......但这不是吗?

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

从我天真的角度来看,两个代码示例完全相同.唯一的区别是第一个使用一些中间变量,而第二个是链接函数调用.

在编译第二个时,它会对我大吼大叫

 - 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
Run Code Online (Sandbox Code Playgroud)

但说实话,我不知道编译器试图告诉我什么.我所理解的是,我有一个终身问题.但为什么?

两个代码示例之间有什么区别?为什么以及如何影响寿命?

Fra*_*gné 6

定义中间变量可延长中间值的生命周期.临时值(例如io::stdin()io::stdin().lock()in io::stdin().lock().lines())在语句结束时不再存在,除非它们被移动(情况就是这样io::stdin().lock()).

let mut lines_iter = io::stdin().lock().lines();:

  • io::stdin() 返回一个新的 Stdin
  • .lock()返回一个新的StdinLock<'a>(引用Stdin;你没有<'a>在文档中看到,因为生命周期在源中被删除)
  • .lines()返回一个新的Lines<StdinLock<'a>>(取得锁的所有权).

返回类型的生命周期参数.lock()表示锁从Stdin对象借用.当你借用某个物体时,该物体必须至少与借用一样长.但是,你试图让一个变量持续到函数结束,但是从一个将在语句末尾删除的对象借用(因为它io::stdin()是一个临时值).

历史记录:当这个问题最初被问到时,.lines()会从锁中借用.现在,.lines()取代锁的所有权.这意味着现在只io::stdin()需要绑定到变量; 它不再需要绑定结果input.lock().

  • 来自主要的“高级”语言,如 java、scala、haskell 或 dart 等......这种行为在我看来非常“令人不安”。我无法想象以这种方式开发更复杂的代码有多烦人。我希望他们尽快解决这个问题。谢谢大家的帮助! (2认同)