我疯狂地试图围绕Rust生命周期问题。运行以下代码时:
use std::fs::File;
use std::io::Read;
use std::clone::Clone;
const BUFSIZE : usize = 4096;
struct LexBuf<T: Read> {
f: T,
buf: [u8; BUFSIZE],
tail: usize,
head: usize
}
impl <T : Read> LexBuf<T> {
fn fetch(&mut self) {
let keepSize = self.head - self.tail + 1;
let mut tmpBuf;
{
let tmpSlice = &self.buf[self.tail..self.head+1];
tmpBuf = tmpSlice.clone();
}
&mut self.buf[0..keepSize]
.clone_from_slice(tmpBuf);
let mut n = self.f
.read(&mut self.buf[keepSize..]).unwrap();
if n < BUFSIZE - keepSize {
self.buf[keepSize+n] = 0;
}
}
}
我希望事实tmpSlice
在其自己的范围内允许我之后借用self.buf
但似乎借用检查员并不同意,因为它说{{1}借用在tmpSlice
范围结束。
答案 0 :(得分:6)
当然它不同意,因为tmpBuf
的生命周期不会在内部块中结束。调用切片的clone()
返回该切片的副本,即指针和长度的副本。出于所有意图和目的,tmpSlice.clone()
返回的切片相当于tmpSlice
,包括其生命周期。因为您将它分配给外部作用域中的tmpBuf
,所以它自然会超出内部块的范围。
实际上,如果Rust允许,您的代码将会中断 - clone_from_slice()
源和目标可能会重叠。例如,如果self.tail
为0
且self.head
为10
,则源和目标完全重叠。
不幸的是,没有办法创建一个在运行时确定大小的固定大小的堆栈数组,所以解决这个问题的唯一方法是通过调用to_owned()
或to_vec()
来分配堆上的数据。在切片上获取Vec<u8>
。
或者,您可以分配第二个固定大小的数组,该数组保证不小于结构中的数组,并将其用作临时空间。您需要使用clone_from_slice()
两次。