我编写了以下代码来读取stdin
中的整数数组:
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let xs: Vec<i32> = line.unwrap()
.trim()
.split(' ')
.map(|s| s.parse().unwrap())
.collect();
println!("{:?}", xs);
}
}
这很好,但是,我觉得let xs
行有点长,所以我把它分成两部分:
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let ss = line.unwrap().trim().split(' ');
let xs: Vec<i32> = ss.map(|s| s.parse().unwrap()).collect();
println!("{:?}", xs);
}
}
这不起作用! Rust回复了以下错误:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:6:18
|
6 | let ss = line.unwrap().trim().split(' ');
| ^^^^^^^^^^^^^ - temporary value dropped here while still borrowed
| |
| temporary value does not live long enough
...
10 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
这让我很困惑。 line
或ss
的活动时间不够长吗?我如何使用let
绑定来延长其生命周期?我以为我已经在使用let
了?
我已经阅读了lifetime guide,但我仍然无法弄明白。谁能给我一个提示?
答案 0 :(得分:13)
在您的第二个版本中,ss
的类型为Split<'a, char>
。类型中的lifetime参数告诉我们该对象包含一个引用。为了使赋值有效,引用必须指向该语句之后存在的对象。但是,unwrap()
消费line
;换句话说,它会将Ok
变体的数据从Result
对象中移出。因此,引用并不指向原始line
内部,而是指向临时对象。
在第一个版本中,虽然调用map
,但在长表达式的末尾使用临时值。要修复第二个版本,您需要绑定unwrap()
的结果以保持值足够长的时间:
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let line = line.unwrap();
let ss = line.trim().split(' ');
let xs: Vec<i32> = ss.map(|s| s.parse().unwrap()).collect();
println!("{:?}", xs);
}
}
答案 1 :(得分:3)
它是关于unwrap()
调用,它正在获取包含的对象,但是这个引用应该比容器对象更长,它在下一行中超出范围(没有本地绑定)。
如果您想获得更清晰的代码,一种非常常见的编写方式是:
use std::io::{self, BufRead};
fn main() {
let stdin = io::stdin();
for line in stdin.lock().lines() {
let xs: Vec<i32> = line.unwrap()
.trim()
.split(' ')
.map(|s| s.parse().unwrap())
.collect();
println!("{:?}", xs);
}
}
如果没有,您可以创建对“未包装”结果的绑定并使用它。