Rust 如何在循环中使用可变状态?
循环:Rust 如何在循环中使用可变状态?,rust,borrow-checker,Rust,Borrow Checker,循环: impl State { pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)> { vec!() } } fn main_loop(mut state: State) { let mut packets = Vec::<(&[u8], SocketAddr)>::new(); loop { let new = st
impl State {
pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)> {
vec!()
}
}
fn main_loop(mut state: State) {
let mut packets = Vec::<(&[u8], SocketAddr)>::new();
loop {
let new = state.exec();
packets.extend(new);
}
}
然而,如果我注释掉packets.extend(new)代码>行,没有错误
我认为问题在于返回的向量属于state
,就好像new
在循环迭代之前就被删除了一样,没有问题。我很高兴能够复制返回的向量,如果这样可以修复它的话
我原以为将.clone()
添加到new
或state.exec()
会修复它,但它没有
有没有简单的方法来解决这个问题
或者我需要以不同的方式构造单线程应用程序状态吗?一种解决方案是:
impl State {
pub fn exec(&mut self) -> Vec<(Vec<u8>, SocketAddr)> {
vec!()
}
}
fn main_loop(mut state: State) {
let mut packets = Vec::<(Vec<u8>, SocketAddr)>::new();
loop {
let new = state.exec();
packets.extend(new);
}
}
impl状态{
发布fn exec(&mut self)->Vec{
vec!()
}
}
fn主回路(mut状态:状态){
让mut packets=Vec:::new();
环路{
让new=state.exec();
数据包。扩展(新);
}
}
我不确定这是否是最好的解决方案,因此我将把这个问题留待讨论
pub fn exec(&mut self) -> Vec<(&[u8], SocketAddr)>
我们将其存储在数据包中。因此,状态
的借用必须至少与数据包类型
的借用时间相同,这是整个功能。因此,从循环的第一次迭代到函数的最后一次,我们再也不能借用状态
,因为可变借用一直持续到函数的最后
要问自己的第一个问题是:你真的需要可变借款吗?如果你能认真地做&self
,那么你的问题就解决了。否则,你将需要以某种方式重新构造事物。类型和[u8]
本质上是无主的。这是对其他人数据的引用。如果获取数据的唯一方法是通过&mut self
,那么您将永远无法按您想要的方式循环。因此,要克隆数据,您需要使用to_vec
,这将和[u8]
转换为vec
(您的类型签名必须更改以反映这一点)。只需更改函数签名,以便返回的和[u8]
不会借用*self
即可编译示例代码:
pub fn exec<'a>(&mut self) -> Vec<(&'a [u8], SocketAddr)> {
vec![]
}
pub fn exec{
vec![]
}
请注意,'a
是一个免费的生存期参数,因此调用者可以在那里提供任何内容(包括'static
),而exec
返回的任何引用都必须满足调用者提供的生存期。实际上,这意味着Vec
只能包含'静态
引用,因为'静态
是唯一一个每隔一个生存期的子类型的生存期
这不可能是你想要的。但是,它可能是,或者[u8]
可能是从其他参数借用的(而不是*self
),或者是从*self
中包含的引用重新借用的。这表明,只需更改签名以更准确地表示输入和输出之间的生命周期关系,有时就可以在不做任何其他更改的情况下修复此类错误。您可以尝试返回对向量的引用吗?@mousetail我认为任何引用,通过可变状态的方法返回,停止循环编译。我理解正确了吗?exec
是否需要执行&mut self
?你可以有两种不同的方法吗,一种是进行突变,另一种是返回切片,后者采用&self
?谢谢,这是一个非常清楚的解释。通过实验,我发现问题出在和[u8]
上。这就解释了为什么在这种情况下,“由于可变借用一直持续到函数结束”对于无可变借用也是一样的,也许这句话有误导性。使用不可变的循环内借用代码就可以了。谢谢,这增加了我的理解。默认生命周期并不总是我们所需要的。
pub fn exec<'a>(&'a mut self) -> Vec<(&'a [u8], SocketAddr)>
let new = state.exec();
packets.extend(new);
pub fn exec<'a>(&mut self) -> Vec<(&'a [u8], SocketAddr)> {
vec![]
}