"Borrowed value does not live long enough",在循环中使用时丢弃
"Borrowed value does not live long enough", dropped when used in a loop
我知道 String
在 loop
的范围结束时被删除并且向量 input
包含 trimmed_text
.
的切片
我想解决方案是将这些切片的所有权移至 input
或类似的名称。这怎么能做到?
use std::io;
fn main() {
let mut input: Vec<&str>;
loop {
let mut input_text = String::new();
println!("Type instruction in the format Add <name> to <department>:");
io::stdin()
.read_line(&mut input_text)
.expect("failed to read from stdin");
let trimmed_text: String = input_text.trim().to_string();
input = trimmed_text.split(" ").collect();
if input[0] == "Add" && input[2] == "to" {
break;
} else {
println!("Invalid format.");
}
}
println!("{:?}", input);
}
编译错误:
error[E0597]: `trimmed_text` does not live long enough
--> src/main.rs:14:17
|
14 | input = trimmed_text.split(" ").collect();
| ^^^^^^^^^^^^ borrowed value does not live long enough
...
21 | }
| - `trimmed_text` dropped here while still borrowed
22 |
23 | println!("{:?}", input);
| ----- borrow later used here
.split()
returns 对 String
的引用在循环结束时被丢弃,但您希望 input
在循环结束后继续存在,所以你应该重构它来保存拥有的值而不是引用。示例:
use std::io;
fn example() {
let mut input: Vec<String>; // changed from &str to String
loop {
let mut input_text = String::new();
println!("Type instruction in the format Add <name> to <department>:");
io::stdin()
.read_line(&mut input_text)
.expect("failed to read from stdin");
// map str refs into owned Strings
input = input_text.trim().split(" ").map(String::from).collect();
if input[0] == "Add" && input[2] == "to" {
break;
} else {
println!("Invalid format.");
}
}
println!("{:?}", input);
}
如您所知,问题是切片的所有者寿命不够长。您没有指出(并且可能没有明确看到)的是所有者是变量 trimmed_text
。所以你想要做的(如果你不想复制每个切片以获得更好的性能)是使 trimmed_text
的范围更大:
use std::io;
fn main() {
let mut input: Vec<&str>;
let mut trimmed_text: String;
loop {
...
trimmed_text = input_text.trim().to_string();
input = trimmed_text.split(" ").collect();
if input[0] == "Add" && input[2] == "to" {
break;
} else {
...
}
}
println!("{:?}", input);
}
在这里,我们解决了切片所有者生命周期的错误。但是,我们还有第二个问题:
13 | trimmed_text = input_text.trim().to_string();
| ^^^^^^^^^^^^ assignment to borrowed `trimmed_text` occurs here
14 |
15 | input = trimmed_text.split(" ").collect();
| ----- ------------ borrow of `trimmed_text` occurs here
| |
| borrow might be used here, when `input` is dropped and runs the `Drop` code for type `std::vec::Vec`
这告诉我们,经过一个循环,input
变量在修改时仍然借用了trimmed_text
。要解决此问题,我们可以缩小输入范围,使输入范围不包含第 13 行:
use std::io;
fn main() {
// Remove the "let mut input: Vec<&str>;"
let mut trimmed_text: String;
loop {
...
trimmed_text = input_text.trim().to_string();
let input: Vec<&str> = trimmed_text.split(" ").collect();
...
}
}
如果我们不在循环外使用 input
,这就可以正常工作。现在我们只需要在循环结束时输出input
的值即可:
use std::io;
fn main() {
// Remove the "let mut input: Vec<&str>;"
let mut trimmed_text: String;
let results = loop {
...
trimmed_text = input_text.trim().to_string();
let input: Vec<&str> = trimmed_text.split(" ").collect();
if input[0] == "Add" && input[2] == "to" {
break input;
}
...
};
println!("{:?}", results);
}
我们找到了!
长话短说:
这是一个无需复制切片即可执行所需操作的代码:
use std::io;
fn main() {
let mut trimmed_text: String;
let results = loop {
let mut input_text = String::new();
println!("Type instruction in the format Add <name> to <department>:");
io::stdin()
.read_line(&mut input_text)
.expect("failed to read from stdin");
trimmed_text = input_text.trim().to_string();
let input: Vec<&str> = trimmed_text.split(" ").collect();
if input[0] == "Add" && input[2] == "to" {
break input;
} else {
println!("Invalid format.");
}
};
println!("{:?}", results);
}
我将 input
重命名为 results
以避免与循环内的 input
变量混淆。如果您真的愿意,请随时将其重命名回 input
。
我知道 String
在 loop
的范围结束时被删除并且向量 input
包含 trimmed_text
.
我想解决方案是将这些切片的所有权移至 input
或类似的名称。这怎么能做到?
use std::io;
fn main() {
let mut input: Vec<&str>;
loop {
let mut input_text = String::new();
println!("Type instruction in the format Add <name> to <department>:");
io::stdin()
.read_line(&mut input_text)
.expect("failed to read from stdin");
let trimmed_text: String = input_text.trim().to_string();
input = trimmed_text.split(" ").collect();
if input[0] == "Add" && input[2] == "to" {
break;
} else {
println!("Invalid format.");
}
}
println!("{:?}", input);
}
编译错误:
error[E0597]: `trimmed_text` does not live long enough
--> src/main.rs:14:17
|
14 | input = trimmed_text.split(" ").collect();
| ^^^^^^^^^^^^ borrowed value does not live long enough
...
21 | }
| - `trimmed_text` dropped here while still borrowed
22 |
23 | println!("{:?}", input);
| ----- borrow later used here
.split()
returns 对 String
的引用在循环结束时被丢弃,但您希望 input
在循环结束后继续存在,所以你应该重构它来保存拥有的值而不是引用。示例:
use std::io;
fn example() {
let mut input: Vec<String>; // changed from &str to String
loop {
let mut input_text = String::new();
println!("Type instruction in the format Add <name> to <department>:");
io::stdin()
.read_line(&mut input_text)
.expect("failed to read from stdin");
// map str refs into owned Strings
input = input_text.trim().split(" ").map(String::from).collect();
if input[0] == "Add" && input[2] == "to" {
break;
} else {
println!("Invalid format.");
}
}
println!("{:?}", input);
}
如您所知,问题是切片的所有者寿命不够长。您没有指出(并且可能没有明确看到)的是所有者是变量 trimmed_text
。所以你想要做的(如果你不想复制每个切片以获得更好的性能)是使 trimmed_text
的范围更大:
use std::io;
fn main() {
let mut input: Vec<&str>;
let mut trimmed_text: String;
loop {
...
trimmed_text = input_text.trim().to_string();
input = trimmed_text.split(" ").collect();
if input[0] == "Add" && input[2] == "to" {
break;
} else {
...
}
}
println!("{:?}", input);
}
在这里,我们解决了切片所有者生命周期的错误。但是,我们还有第二个问题:
13 | trimmed_text = input_text.trim().to_string();
| ^^^^^^^^^^^^ assignment to borrowed `trimmed_text` occurs here
14 |
15 | input = trimmed_text.split(" ").collect();
| ----- ------------ borrow of `trimmed_text` occurs here
| |
| borrow might be used here, when `input` is dropped and runs the `Drop` code for type `std::vec::Vec`
这告诉我们,经过一个循环,input
变量在修改时仍然借用了trimmed_text
。要解决此问题,我们可以缩小输入范围,使输入范围不包含第 13 行:
use std::io;
fn main() {
// Remove the "let mut input: Vec<&str>;"
let mut trimmed_text: String;
loop {
...
trimmed_text = input_text.trim().to_string();
let input: Vec<&str> = trimmed_text.split(" ").collect();
...
}
}
如果我们不在循环外使用 input
,这就可以正常工作。现在我们只需要在循环结束时输出input
的值即可:
use std::io;
fn main() {
// Remove the "let mut input: Vec<&str>;"
let mut trimmed_text: String;
let results = loop {
...
trimmed_text = input_text.trim().to_string();
let input: Vec<&str> = trimmed_text.split(" ").collect();
if input[0] == "Add" && input[2] == "to" {
break input;
}
...
};
println!("{:?}", results);
}
我们找到了!
长话短说:
这是一个无需复制切片即可执行所需操作的代码:
use std::io;
fn main() {
let mut trimmed_text: String;
let results = loop {
let mut input_text = String::new();
println!("Type instruction in the format Add <name> to <department>:");
io::stdin()
.read_line(&mut input_text)
.expect("failed to read from stdin");
trimmed_text = input_text.trim().to_string();
let input: Vec<&str> = trimmed_text.split(" ").collect();
if input[0] == "Add" && input[2] == "to" {
break input;
} else {
println!("Invalid format.");
}
};
println!("{:?}", results);
}
我将 input
重命名为 results
以避免与循环内的 input
变量混淆。如果您真的愿意,请随时将其重命名回 input
。