【发布时间】:2020-04-21 08:22:50
【问题描述】:
我正在处理一个庞大的 TSV(制表符分隔值)文件,并希望尽可能高效地执行此操作。为此,我想我会通过在循环之前预先分配它来防止为每一行分配一个新的Vec:
let mut line = String::new();
let mut fields = Vec::with_capacity(headers.len());
while reader.read_line(&mut line)? > 0 {
fields.extend(line.split('\t'));
// do something with fields
fields.clear();
}
当然,借用检查器并不好笑,因为我们正在覆盖line,而fields 可能仍然有对它的引用:
error[E0502]: cannot borrow `line` as mutable because it is also borrowed as immutable
--> src/main.rs:66:28
|
66 | while reader.read_line(&mut line)? > 0 {
| ^^^^^^^^^ mutable borrow occurs here
67 | fields.extend(line.split('\t'));
| ------ ---- immutable borrow occurs here
| |
| immutable borrow later used here
这实际上不是问题,因为fields.clear(); 删除了所有引用,因此在循环开始时调用read_line(&mut line) 时,fields 实际上并没有从line 借用任何东西。
但是我该如何通知借阅检查器呢?
【问题讨论】:
-
也许看看它在
csv中是如何工作的?还是直接使用csv设置自定义分隔符?它有摊销分配的配方。 -
csv还做了更多我不需要的工作,比如处理带引号的字符串,所以我认为手动方式会更快。除了解析之外,我在这里做的处理真的很少。 -
我记得我看到了令我惊讶的情况,循环中的分配被完全优化掉了,所以也许不需要这样做。我还想知道您在“使用字段做某事”时到底在做什么——这真的需要
Vec,还是您可以直接使用迭代器? -
@SvenMarnach 我正在获取一些字段的值(我从标题中推断出它们的索引)并聚合它们。我确实可以直接使用迭代器,但这会很麻烦,因为我将依赖特定的字段顺序。无论如何,我的优化可能还为时过早,但出于教育目的,我仍然对这个问题的答案感兴趣:)
标签: rust borrow-checker