2017-08-05 167 views
-3

我寫了這個簡單的輸入解析:如何知道什麼時候借結束

use std::io; 

fn main() { 
    let mut line = String::new(); 

    io::stdin().read_line(&mut line) 
     .expect("Cannot read line."); 

    let parts = line.split_whitespace(); 

    for p in parts { 
     println!("{}", p); 
    } 

    line.clear(); 
    io::stdin().read_line(&mut line) 
     .expect("Cannot read line."); 

} 

上面的代碼創建了一個String對象,讀取一行進去,用空白,並打印輸出,他分裂了。然後它嘗試使用相同的String對象執行相同的操作。在編譯時,我得到錯誤:

--> src/main.rs:15:5 
    | 
9 |  let parts = line.split_whitespace(); 
    |     ---- immutable borrow occurs here 
... 
15 |  line.clear(); 
    |  ^^^^ mutable borrow occurs here 
... 
19 | } 
    | - immutable borrow ends here 

由於Stringowned by an iterator。該解決方案被描述爲:

let parts: Vec<String> = line.split_whitespace() 
    .map(|s| String::from(s)) 
    .collect(); 

我有幾個問題在這裏:

  1. 我已經通過調用每個在它消耗的迭代器。它的借款應該已經結束。
  2. 如何從函數定義中知道借用的生命期?
  3. 如果一個函數是借用一個對象,我怎麼知道它釋放它?例如在解決方案中使用collect()釋放借入。

我想我在這裏錯過了一個重要的概念。

+1

請僅發佈[每個問題一個問題](https://meta.stackexchange.com/q/39223/281829)。 – Shepmaster

+0

這些是與相同概念相關的相關問題,因此發佈三個單獨的問題並不會富有成效。 – Xolve

回答

1

代碼中的問題是,您將line.split_whitespace()的結果綁定到名稱(parts)。如果你這樣寫:

io::stdin().read_line(&mut line) 
    .expect("Cannot read line."); 

for p in line.split_whitespace() { // <-- pass directly into loop 
    println!("{}", p); 
} 

line.clear(); 
io::stdin().read_line(&mut line) 
    .expect("Cannot read line."); 

這樣,它只是工作。另一種可能性是,人爲地限制parts的壽命,就像這樣:

io::stdin().read_line(&mut line) 
    .expect("Cannot read line."); 

{ 
    let parts = line.split_whitespace(); 

    for p in parts { 
     println!("{}", p); 
    } 
} 

line.clear(); 
io::stdin().read_line(&mut line) 
    .expect("Cannot read line."); 

這也適用。


那麼,爲什麼呢?這是由於編譯器目前的工作原理,通常稱爲「詞彙借用」。這裏的問題是每個包含借款的非暫時性價值都將「活着」直到其範圍結束。

對於您的情況:由於您將split_whitespace()(借用該字符串)的結果指定爲parts,因此該借入是「存活」的,直到parts的範圍結束爲止。 不是直到parts的生命週期結束。

在這個答案的第一個版本中,我們沒有綁定一個名稱的值,因此split_whitespace()的結果只是一個臨時的借位並沒有擴展到整個範圍。這也是爲什麼你的collect()例子工作原因:不是因爲collect(),但因爲從來沒有一個名字綁定到借用字符串的東西。在我的第二個版本中,我們只是限制了範圍。

請注意,這是編譯器的一個已知的缺點。你是對的,編譯器就是看不到它。

相關問題