【发布时间】:2017-02-18 04:13:21
【问题描述】:
以下代码从标准输入读取以空格分隔的记录,并将逗号分隔的记录写入标准输出。即使使用优化的构建,它也相当慢(大约是使用 awk 的两倍)。
use std::io::BufRead;
fn main() {
let stdin = std::io::stdin();
for line in stdin.lock().lines().map(|x| x.unwrap()) {
let fields: Vec<_> = line.split(' ').collect();
println!("{}", fields.join(","));
}
}
一个明显的改进是使用itertools 加入而不分配向量(collect 调用会导致分配)。但是,我尝试了另一种方法:
fn main() {
let stdin = std::io::stdin();
let mut cache = Vec::<&str>::new();
for line in stdin.lock().lines().map(|x| x.unwrap()) {
cache.extend(line.split(' '));
println!("{}", cache.join(","));
cache.clear();
}
}
此版本尝试一遍又一遍地重用相同的向量。不幸的是,编译器抱怨:
error: `line` does not live long enough
--> src/main.rs:7:22
|
7 | cache.extend(line.split(' '));
| ^^^^
|
note: reference must be valid for the block suffix following statement 1 at 5:39...
--> src/main.rs:5:40
|
5 | let mut cache = Vec::<&str>::new();
| ^
note: ...but borrowed value is only valid for the for at 6:4
--> src/main.rs:6:5
|
6 | for line in stdin.lock().lines().map(|x| x.unwrap()) {
| ^
error: aborting due to previous error
这当然是有道理的:line 变量仅在for 循环体中有效,而cache 在迭代中保持指向它的指针。但是这个错误在我看来仍然是虚假的:因为每次迭代后缓存都是 cleared,所以不能保留对 line 的引用,对吧?
我如何告诉借阅检查员这件事?
【问题讨论】:
-
“不能保留对
line的引用,对吧?” → 对。但是,borrowck 是怎么知道的呢? -
我会注意到
line是分配的String:即使Vec缓存有效,每次迭代仍然需要新的内存分配。 -
@mcarton:没错:这就是为什么我要问我如何告诉借阅检查员这件事:)
-
@MatthieuM。我很想知道一种方法来重用该字符串的内存:) 但作为一个单独的问题可能会更好。
-
@Clément 为避免每次都重新分配
line,您应该使用read_line而不是lines
标签: rust lifetime borrow-checker