Memory management 使用选项<&;mut>;两次

Memory management 使用选项<&;mut>;两次,memory-management,rust,Memory Management,Rust,以下程序编译良好: fn write_u16(bytes: &mut Vec<u8>, value: u16) { bytes.push((value >> 8) as u8); bytes.push(value as u8); } fn write_u32(bytes: &mut Vec<u8>, value: u32) { write_u16(bytes, (value >> 16) as u16);

以下程序编译良好:

fn write_u16(bytes: &mut Vec<u8>, value: u16) {
    bytes.push((value >> 8) as u8);
    bytes.push(value as u8);
}

fn write_u32(bytes: &mut Vec<u8>, value: u32) {
    write_u16(bytes, (value >> 16) as u16);
    write_u16(bytes, value as u16);
}
fn write_u16(字节:&mut Vec,值:u16){
字节。推送((值>>8)为u8);
字节。推送(值为u8);
}
fn write_u32(字节:&mut Vec,值:u32){
将u16(字节,(值>>16)写入为u16);
写入_u16(字节,值为u16);
}
现在,我将字节类型更改为选项:

fn write\u u16(字节\u opt:Option,值:u16){
如果让一些(字节)=字节{
字节。推送((值>>8)为u8);
字节。推送(值为u8);
}
}
fn写入_u32(字节_opt:Option,值:u32){
将_u16(字节_opt,(值>>16)写入为u16);
写入_u16(字节_opt,值为u16);
}
程序现在不编译:

main.rs:10:15: 10:24 error: use of moved value: `bytes_opt`
main.rs:10     write_u16(bytes_opt, value as u16);
                         ^~~~~~~~~
main.rs:9:15: 9:24 note: `bytes_opt` moved here because it has type `core::option::Option<&mut collections::vec::Vec<u8>>`, which is non-copyable
main.rs:9     write_u16(bytes_opt, (value >> 16) as u16);
                        ^~~~~~~~~
error: aborting due to previous error
main.rs:10:15:10:24错误:使用移动值:`bytes\u opt`
main.rs:10 write_u16(字节_opt,值为u16);
^~~~~~~~~
main.rs:9:15:9:24注意:`bytes\u opt`移到这里是因为它的类型为`core::option::option`,这是不可复制的
main.rs:9写入u16(字节选择,(值>>16)作为u16);
^~~~~~~~~
错误:由于上一个错误而中止
我真的不明白,为什么我不能使用选项两次,我该如何解决这个问题

我能想象的解决这个问题的唯一方法是:

fn write_u32(bytes_opt: Option<&mut Vec<u8>>, value: u32) {
    if let Some(bytes) = bytes_opt {
        write_u16(Some(bytes), (value >> 16) as u16);
        write_u16(Some(bytes), value as u16);
    } else {
        write_u16(None, (value >> 16) as u16);
        write_u16(None, value as u16);
    }
}
fn写入\u u32(字节\u选项:选项,值:u32){
如果让一些(字节)=字节{
将_u16(某些(字节),(值>>16)写入为u16);
写入_u16(一些(字节),值为u16);
}否则{
将_u16(无,(值>>16)写入为u16);
写入_u16(无,值为u16);
}
}

但这不是很好的代码。

错误消息告诉您它们是关键:

bytes\u opt
移动到此处,因为它的类型为
core::option::option
,不可复制

函数签名声明它将使用参数:

fn write_u16(bytes_opt: Option<&mut Vec<u8>>, value: u16)
//                      ^~~~~~~~~~~~~~~~~~~~
在@ChrisMorgan的提示下,我得到了一些符合您原始API的东西:

fn write_u16(bytes_opt: Option<&mut Vec<u8>>, value: u16) {
    if let Some(bytes) = bytes_opt {
        bytes.push((value >> 8) as u8);
        bytes.push(value as u8);
    }
}

fn write_u32(bytes_opt: Option<&mut Vec<u8>>, value: u32) {
    if let Some(bytes) = bytes_opt {
        write_u16(Some(bytes), (value >> 16) as u16);
        write_u16(Some(bytes), value as u16);
    }
}
fn write\u u16(字节\u opt:Option,值:u16){
如果让一些(字节)=字节{
字节。推送((值>>8)为u8);
字节。推送(值为u8);
}
}
fn写入_u32(字节_opt:Option,值:u32){
如果让一些(字节)=字节{
将_u16(某些(字节),(值>>16)写入为u16);
写入_u16(一些(字节),值为u16);
}
}

错误消息告诉您他们的关键内容:

bytes\u opt
移动到此处,因为它的类型为
core::option::option
,不可复制

函数签名声明它将使用参数:

fn write_u16(bytes_opt: Option<&mut Vec<u8>>, value: u16)
//                      ^~~~~~~~~~~~~~~~~~~~
在@ChrisMorgan的提示下,我得到了一些符合您原始API的东西:

fn write_u16(bytes_opt: Option<&mut Vec<u8>>, value: u16) {
    if let Some(bytes) = bytes_opt {
        bytes.push((value >> 8) as u8);
        bytes.push(value as u8);
    }
}

fn write_u32(bytes_opt: Option<&mut Vec<u8>>, value: u32) {
    if let Some(bytes) = bytes_opt {
        write_u16(Some(bytes), (value >> 16) as u16);
        write_u16(Some(bytes), value as u16);
    }
}
fn write\u u16(字节\u opt:Option,值:u16){
如果让一些(字节)=字节{
字节。推送((值>>8)为u8);
字节。推送(值为u8);
}
}
fn写入_u32(字节_opt:Option,值:u32){
如果让一些(字节)=字节{
将_u16(某些(字节),(值>>16)写入为u16);
写入_u16(一些(字节),值为u16);
}
}

尽管我怀疑在这种情况下,您不应该这样做(正如前面所评论的),但在安全的情况下,可以为这种情况重新引用可变引用:

fn write_u32(多字节_opt:Option,值:u32){
将_u16(字节_opt.as _mut().map(| x |&mut**x)(值>>16)写入为u16);
写入_u16(字节_opt,值为u16);
}

bytes_opt.as_mut().map(|x |&mut**x)
也可以写入
match bytes_opt{Some(&mut ref mut x)=>Some(x),None=>None,}
。这是一个非常令人费解的模式(从左到右阅读:
&mut
-取消对包含值的引用,
ref mut
-然后对其进行新的可变引用),但它可以工作并避免所有权问题。

尽管我怀疑在这种情况下,您不应该这样做(如已评论的那样),对于这种情况,在安全的情况下,可以重新加载可变引用:

fn write_u32(多字节_opt:Option,值:u32){
将_u16(字节_opt.as _mut().map(| x |&mut**x)(值>>16)写入为u16);
写入_u16(字节_opt,值为u16);
}

bytes_opt.as_mut().map(|x |&mut**x)
也可以写入
match bytes_opt{Some(&mut ref mut x)=>Some(x),None=>None,}
。这是一个非常令人费解的模式(从左到右阅读:
&mut
-取消对包含值的引用,
ref mut
-然后对其进行新的可变引用),但它可以工作并避免所有权问题。

每次使用
&mut选项
肯定比重建
选项
更糟糕,因为API受到了损害。@感谢您向更好的方向轻轻推动。您在第二种情况下的语义略有不同,您不会使用
None
调用
write\u u16
。实际上,我需要使用
Some
None
调用所有方法,不管它们有什么。在我的真实代码方法中,
write_u16
稍微复杂一些,即使
None
通过,也能做有用的工作。每次使用
&mut选项
肯定比重建
选项
更糟糕,因为API受到了损害。@感谢您向更好的方向轻轻推动。您在第二种情况下的语义略有不同,您不会使用
None
调用
write\u u16
。实际上,我需要使用
Some
None
调用所有方法,不管它们有什么。在我的真实代码方法中,
write_u16
稍微复杂一些,即使通过了
None
也能做有用的工作。如果
write_u16(None,
是一个noop,我对
选项的使用提出质疑
write_16(选项,值)
可以是
option.map(|字节| write_16(字节,值))
。我想你通常会直接处理向量,而不是一个选项。这不是一个noop,这是一个简化的例子。在我的代码中,我使用
pos:&mut usiz