Rust的read_line函数为什么使用可变引用而不是返回值?

10

考虑以下代码来读取 Rust 中的用户输入:

use std::io;
fn main() {
    let mut input = String::new();
    io::stdin()
        .read_line(&mut input)
        .expect("error: unable to read user input");
    println!("{}", input);
}

为什么不能像这样做?

use std::io;
fn main() {
    let mut input = io::stdin()
        .read_line()
        .expect("error: unable to read user input");
    println!("{}", input);
}

这将使其他语言更加方便。


如果需要的话,你可以轻松编写一个实现所需功能的函数。此外,你可以使用 read_line 来完成它,但是反过来就不行了。 - Ekrem Dinçel
1个回答

17

简而言之,最接近你要的是lines(),而read_line之所以像这样工作是为了效率。使用lines()的版本如下:

use std::io::{self, BufRead};

fn main() {
    // get next line from stdin and print it
    let input = io::stdin().lock().lines().next().unwrap().expect("IO error");
    println!("{}", input);
}

一般来说,read_line()不适用于小型交互式程序;有更好的方法来实现这些。

read_line方法来自通用的io::BufRead特性,它的主要用途是读取输入,通常是从文件或其他程序重定向,并可能以大量方式出现。处理大量数据时,最好最小化执行的分配次数,这就是为什么read_line被设计为重用现有字符串的原因。一个典型的模式是:

let mut line = String::new();
while input.read_line(&mut line)? != 0 {
    // do something with line
    ...
    line.clear();
}

为了尽可能减少重新分配的次数,line 只会在需要容纳输入行时才会增长。一旦达到典型的大小,分配将变得非常罕见,一旦读取最大的行,它们就会完全消失。如果 read_line() 支持“方便”的接口,则上述循环确实会更好看 - 例如:

while let Some(line) = read_new_line(some_input)? {
    // process the line
    ...
}

...但是这将需要为每行进行新的分配和释放。在一次性或学习性程序中,这可能完全没有问题,但是BufRead旨在用作高效IO的构建块,因此它的read_line方法注重性能而不是方便。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接