Rust 无法移出可变引用后面的***
我有下一个代码:Rust 无法移出可变引用后面的***,rust,Rust,我有下一个代码: struct Tokenizer { reader: BufReader<File>, buf: Vec<u8>, token: String } impl Tokenizer { fn new(path: &PathBuf) -> Tokenizer { let file = File::open(path).expect("Unable to open file!")
struct Tokenizer {
reader: BufReader<File>,
buf: Vec<u8>,
token: String
}
impl Tokenizer {
fn new(path: &PathBuf) -> Tokenizer {
let file = File::open(path).expect("Unable to open file!");
Tokenizer {
reader: BufReader::new(file),
buf: Vec::<u8>::new(),
token: String::new()
}
}
fn next(&mut self) -> bool {
if self.buf.len() == 0 {
if self.reader.read_until(b'\n', &mut self.buf)
.expect("Unable to read file") == 0 {
return false;
}
}
let s = String::from_utf8(self.buf).expect("Unable to read file");
let mut start: i8 = -1;
let mut end: i8 = -1;
for (i, c) in s.char_indices() {
if start == -1 {
if !c.is_whitespace() {
start = i as i8;
}
} else {
if c.is_whitespace() {
end = i as i8;
}
}
}
self.token = s.chars().skip(start as usize).take((end - start) as usize).collect();
self.buf = s.into_bytes();
self.buf.clear();
return true;
}
}
struct标记器{
读者:BufReader,
buf:Vec,
令牌:字符串
}
impl标记器{
fn新建(路径:&PathBuf)->标记器{
让file=file::open(path).expect(“无法打开文件!”);
标记器{
读卡器:BufReader::new(文件),
buf:Vec:::new(),
令牌:String::new()
}
}
fn下一步(&mut self)->bool{
如果self.buf.len()=0{
if self.reader.read_直到(b'\n',&mut self.buf)
.expect(“无法读取文件”)==0{
返回false;
}
}
让s=String::from_utf8(self.buf).expect(“无法读取文件”);
让mut开始:i8=-1;
让mut结束:i8=-1;
对于s.char_索引()中的(i,c){
如果开始==-1{
if!c.是_空格(){
开始=i为i8;
}
}否则{
如果c.is_whitespace(){
end=i为i8;
}
}
}
self.token=s.chars();
self.buf=s.到_字节();
self.buf.clear();
返回true;
}
}
但由于错误,它无法工作:
error[E0507]: cannot move out of `self.buf` which is behind a mutable reference
--> src\parser.rs:28:35
|
28 | let s = String::from_utf8(self.buf).expect("Unable to read file");
| ^^^^^^^^ move occurs because `self.buf` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait
error[E0507]:无法移出可变引用后面的'self.buf'
-->src\parser.rs:28:35
|
28 | let s=String::from_utf8(self.buf).expect(“无法读取文件”);
|^^^^^^^^发生移动是因为'self.buf'的类型为'std::vec::vec',该类型未实现'Copy'特性
我读过类似的问题,建议使用
swap
,但我不知道这对我有什么帮助。如何修复此错误以及它为什么不编译?您得到此错误的原因是String::from\u utf8
试图获得其参数的所有权。在您的例子中,它是&mut self
的属性,它被引用(您计划将来使用这个结构,而不是使用它)
简单的解决方法是使用其他参考功能:
fn next(&mut self)->bool{
...
设s=String::from_utf8_lossy(&self.buf[…]);
...
}
并将self.buf=s.删除为_字节()代码>行,因为你是1。在下一行清洗;2.它没有被使用,而是被引用。
String::from_utf8
按值获取其参数,这意味着它不只是使用给定的向量,而是使用它
但是在这里它不能使用输入:因为self
只是一个可变借用self。buf
最多是一个可变借用(aka&mut-Vec
),因此签名不匹配。这是因为String::from_utf8
将检查输入是否有效,然后将其重新解释为有效字符串,以避免新的分配
有两种简单的方法可以解决这个问题:
最简单的方法是使用一个函数,该函数以引用作为输入,这将在内部分配一个新字符串以返回数据,因此效率稍低,但更方便
另一种选择——以及您得到的swap
建议——是将数据移出借用:如果您有一个可变借用,您不能使用self.buf
,但可以用一个新的(拥有的)缓冲区替换它
swap
执行此操作并返回旧值,因此您可以将self.buf
的当前内容交换为全新(空)向量,并取出以前称为self.buf
的向量,该向量现在归您所有(而不是self
),因此是可消费的
这里看起来是这样的:
让mut buf=Vec::new();
交换(&mut buf,self.buf);
//现在我们使用交换的buf
让s=String::from_utf8(buf).expect(“无法读取文件”);
让mut开始:i8=-1;
让mut结束:i8=-1;
对于s.char_索引()中的(i,c){
如果开始==-1{
if!c.是_空格(){
开始=i为i8;
}
}否则{
如果c.is_whitespace(){
end=i为i8;
}
}
}
self.token=s.chars();
self.buf=s.到_字节();
self.buf.clear();
返回true;
在这种情况下,我认为str::from_utf8
更合适。@rodrigo这是一个非消费函数的例子;)谢谢你的回答,我会尽量使用你的变体而不应对。