为什么可以在对 File 的不可变引用上实现 Read?
Why is it possible to implement Read on an immutable reference to File?
如果您查看 docs for Read
,大多数方法都接受 &mut self
。这是有道理的,因为读取某物通常会更新内部偏移量,因此下一次读取 returns 不同的数据。然而,这编译:
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);
}
该文件不可变,但肯定正在读入数据。这对我来说似乎不正确。 ,但一个不可变实例看似正在发生变异这一事实似乎仍然很奇怪。
正如@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
的新临时值。使用 mutable 对表达式的引用没有问题(例如 &mut 42
)。这正是这里发生的事情。表达式是对 immutable 值的引用这一事实并不重要,因为我们实际上无法通过 &mut &T
.
来改变该值
关于为什么我们不需要 File
为 mutable 的问题:File
基本上只是一个新类型的文件描述符,即打开文件的索引table 即由 OS 管理。 read
和朋友根本不会改变这个描述符,这就是 File
不需要突变的原因。当然会发生变异,但这是由操作系统在其自己的数据结构上完成的,而不是在您的用户态 rust 代码中完成的。
如果您查看 docs for Read
,大多数方法都接受 &mut self
。这是有道理的,因为读取某物通常会更新内部偏移量,因此下一次读取 returns 不同的数据。然而,这编译:
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);
}
该文件不可变,但肯定正在读入数据。这对我来说似乎不正确。
正如@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
的新临时值。使用 mutable 对表达式的引用没有问题(例如 &mut 42
)。这正是这里发生的事情。表达式是对 immutable 值的引用这一事实并不重要,因为我们实际上无法通过 &mut &T
.
关于为什么我们不需要 File
为 mutable 的问题:File
基本上只是一个新类型的文件描述符,即打开文件的索引table 即由 OS 管理。 read
和朋友根本不会改变这个描述符,这就是 File
不需要突变的原因。当然会发生变异,但这是由操作系统在其自己的数据结构上完成的,而不是在您的用户态 rust 代码中完成的。