首页 文章

传递可变引用与创建和返回拥有值是否总是更可取?

提问于
浏览
1

从像Python这样的动态语言来到Rust,我不熟悉编程模式,在这种编程模式中,你提供了一个函数,该函数具有对空数据结构的可变引用,并且该函数填充它 . 一个典型的例子是将文件读入 String

let mut f = File::open("file.txt").unwrap();
let mut contents = String::new();
f.read_to_string(&mut contents).unwrap();

对于我习惯使用Python的眼睛,你只需在函数中创建一个自有值并将其作为返回值移出的API看起来更直观/符合人体工程学/你有什么:

let mut f = File::open("file.txt").unwrap();
let contents = f.read_to_string().unwrap();

由于Rust标准库采用了以前的道路,我认为必须有一个原因 .

是否总是更喜欢使用参考模式?如果是这样,为什么? (性能原因?具体是什么?)如果不是,我如何发现可能有益的情况?除了填充结果数据结构之外,当我想要返回另一个值时,它是否最有用(如上面的第一个例子,其中 .read_to_string() 返回读取的字节数)?为什么不使用元组?这仅仅是个人偏好的问题吗?

1 回答

  • 8

    如果 read_to_string 想要返回一个拥有的 String ,这意味着每次调用它时都必须堆分配一个新的 String . 此外,由于 Read 实现并不总是知道要读取多少数据,因此可能需要多次逐步重新分配正在进行的工作 String . 这也意味着每个临时的 String 都必须返回到要销毁的分配器 .

    这很浪费 . Rust是一种系统编程语言 . 系统编程语言厌恶浪费 .

    相反,调用者负责分配和提供缓冲区 . 如果您只调用一次 read_to_string ,则不会发生任何变化 . 但是,如果多次调用它,则可以多次重复使用相同的缓冲区,而不需要进行常量分配/调整大小/取消分配循环 . 虽然它不适用于这种特定情况,但类似的接口可以设计为也支持堆栈缓冲区,这意味着在某些情况下您可以完全避免堆活动 .

    让调用者通过缓冲区比替代方案更灵活 .

相关问题