我有一个fn
看起来像这样:
use std::io::Read;
fn read_something(file: &mut impl Read) {
let _ = file.read(&mut [0; 8]);
}
当我像这样传递一个Vec
的切片时:
fn main() {
let vector = vec![1, 2, 3, 4];
read_something(&mut &vector[..]);
}
可以正常工作。但是,当我首先将切片保存到一个变量中时,它不会编译:
fn main() {
let vector = vec![1, 2, 3, 4];
let slice = &vector[..];
read_something(&mut slice);
}
编译器告诉我
不能借用为可变
游乐场
这两种情况有什么不同?为什么第一个例子工作,即使vector
不声明为可变的吗?我怎么能把&[u8]
片传给吃&mut impl Read
的fn
片呢?
我如何将&[u8]切片传递到fn中,它会吃掉&mut impl Read?
将mut
添加到保存切片的变量中:
let vector = vec![1, 2, 3, 4];
let mut slice = &vector[..];
read_something(&mut slice);
注意,这使得切片可变,这意味着它可以被修改以引用不同的数据(read_something()
使用)。它不允许切片改变不可变向量。
这两种情况有什么不同?为什么第一个例子工作,即使矢量没有声明为可变的吗?
在第一种情况下,vector是不可变的,但是保存切片的未命名临时对象是。你的第一个例子是这样的:
let vector = vec![1, 2, 3, 4]; // immutable Vec
let mut tmp = &vector[..]; // mutable slice referring to immutable Vec
read_something(&mut tmp);
// here `tmp` may be pointing to different content
// (e.g. a subset of the vector, or something static)
vector不需要是可变的,因为Read::read()
对&[u8]
的impl不试图修改slice的内容,它只修改slice本身(概念上是一个<指针,length>元组)。它可以这样做,因为Read
是为&[u8]
实现的,所以当<&[u8] as Read>::read()
接收到&mut self
时,它的完整类型是&mut &[u8]
——一个对某些不可变数据片的可变引用。
Read::read()
对于&[u8]
所做的是将接收到的片替换为包含片中尚未读取部分的更小的片。(这允许"相同的";片传递给read()
,最终耗尽所有数据。)由于您读取到的8字节缓冲区大于作为读取源的4字节片,因此在read_something()
返回(playground)后,修改后的tmp
片将为空。