當我遇到這個錯誤時,我正在決議檔案中的一些字串輸入。通常,如果您將一系列方法鏈接在一行上或將它們分成多個操作,則不會有什么不同。然而在這里,當方法鏈在一行中時它不會編譯。
拆分為多個陳述句時,我沒有收到錯誤訊息(鏈接到操場)
let input = std::fs::read_to_string("tst_input.txt").expect("Failed to read input");
let input = input
.lines()
.map(|l| {
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
)
})
.collect::<Vec<_>>();
當它在像這樣的單個陳述句中時,我得到一個終生錯誤(鏈接到操場)
let input = std::fs::read_to_string("tst_input.txt")
.expect("Failed to read input")
.lines()
.map(|l| {
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
iter.next()
.unwrap()
.split_whitespace()
.collect::<Vec<&str>>(),
)
})
.collect::<Vec<_>>()
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:2:17
|
2 | let input = std::fs::read_to_string("tst_input.txt")
| _________________^
3 | | .expect("Failed to read input")
| |_______________________________________^ creates a temporary which is freed while still in use
...
18 | .collect::<Vec<_>>();
| - temporary value is freed at the end of this statement
19 | println!("{:?}", input);
| ----- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
這兩種情況是否應該有效相同?為什么編譯器對它們的處理方式不同?這可能是編譯器錯誤嗎?
uj5u.com熱心網友回復:
這兩種情況并不相同,因為存盤的資訊不同。
在 Rust 中,變數具有語意含義:它們充當存盤資訊的地方,更重要的是,它們定義了這些資訊何時被銷毀——這是由Droptrait處理的。默認情況下,drop為每個超出范圍的變數呼叫方法;這可以被mem::forget和其他一些函式覆寫Box::into_raw,但這些都是非常小眾的情況。
在第一種情況下,正在讀取的資料存盤在input型別為 的變數中String。這種型別wrapsVec<u8>,它實作了Drop,所以當input超出范圍時,這個資料被釋放。然后,第二個input變數是型別Vec<(Vec<&str>, Vec<&str>)>- 你可以看到它包含一個參考,所以它是從第一個借用的input,所以它必須不再存在于源字串之后。在這里,這是滿足的 - 當然,只要您不嘗試將這個值回傳到堆疊中,在這種情況下,源字串將被洗掉,并且參考將懸空。
然而,在單行版本中,字串沒有存盤在任何地方——它是一個臨時的,它在陳述句結束時被銷毀。這就是為什么你不能持有任何對它的參考。但是,您可以通過插入額外的映射操作來創建拆分資料的擁有版本:
let _: Vec<(Vec<String>, Vec<String>)> = std::fs::read_to_string("tst_input.txt")
.expect("Failed to read input")
// This iterator borrows from the temporary...
.lines()
.map(|l| {
// ...this iterator reborrows that borrow...
let mut iter = l.split(" | ");
(
iter.next()
.unwrap()
.split_whitespace()
// ...and this operation clones the source data,
// so they are copied to the new owned location,
// and not referenced anymore, so can be freely dropped
.map(str::to_owned)
.collect::<Vec<_>>(),
iter.next()
.unwrap()
.split_whitespace()
.map(str::to_owned)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>();
uj5u.com熱心網友回復:
對問題進行最少的重新創建可能會有所幫助
let split_value = String::from("example")// <- string owned value
.split("x");
// string has no owner, so its lifetime ends
println!("{:?}", split_value); //error
參考不能超過它參考的值的生命周期。因為字串沒有存盤在任何地方,因此沒有所有者,值的生命周期結束。
并且因為split回傳參考該字串值的資料,所以它的生命周期與該字串相關聯,因此它也結束。
通過將結果存盤在一個變數中,字串現在具有超過運算式的生命周期。
let str_result = String::from("example"); //str_result owns the string value
let split_value = s.split("x");
println!("{:?}", r);
split_value可以列印,因為str_result的生命周期在函式結束時結束,因此參考str_result也是有效的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/394403.html
上一篇:使用JavaFX完成劊子手游戲
