为什么可以对File的不可变引用实现Read?

时间:2015-07-19 16:42:37

标签: rust immutability

如果您查看docs for Read,则大多数方法都会接受&mut self。这是有道理的,因为从某物读取通常会更新内部偏移量,因此下一次读取将返回不同的数据。但是,这会编译:

use std::io::Read;
use std::fs::File;

fn main() {
    let file = File::open("/etc/hosts").unwrap();
    let vec = &mut Vec::new();
    (&file).read_to_end(vec).unwrap();
    println!("{:?}", vec);
}

该文件不可变,但数据肯定被读入。这对我来说似乎不对。 It was pointed out that there is an impl<'a> Read for &'a File,但不可变实例似乎正在变异的事实似乎仍然很奇怪。

1 个答案:

答案 0 :(得分:9)

正如@kennytm所指出的,a.read_to_end(vec)相当于Read::read_to_end(&mut a, vec),因此(&file).read_to_end(vec)扩展为Read::read_to_end(&mut &file, vec)。在后一种表达式中,&file&File类型的新临时值。对表达式进行可变引用没有问题(例如&mut 42)。这正是这里发生的事情。表达式是对不可变值的引用这一事实无关紧要,因为我们实际上无法通过&mut &T来改变该值。

关于为什么我们不需要File是可变的问题:File基本上只是一个新形式的文件描述符,即由OS管理的开放文件表的索引。 read和朋友根本不会改变这个描述符,这就是File不需要变异的原因。当然存在突变,但这是由操作系统在其自己的数据结构上完成的,而不是在用户土地生锈代码中。