首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Option<&mut> 2次

使用Option<&mut> 2次
EN

Stack Overflow用户
提问于 2015-03-29 21:38:33
回答 2查看 94关注 0票数 0

以下程序编译得很好:

代码语言:javascript
复制
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);
}

现在,我将将字节类型更改为Option<&mut Vec>:

代码语言:javascript
复制
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) {
    write_u16(bytes_opt, (value >> 16) as u16);
    write_u16(bytes_opt, value as u16);
}

该程序现在不编译:

代码语言:javascript
复制
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

我真的不明白,为什么我不能使用两次选项,以及如何解决这个问题?

我唯一能想到的解决这个问题的办法是:

代码语言:javascript
复制
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);
    }
}

但这不是很好的密码。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-30 00:13:06

虽然我怀疑在这种情况下您不应该这样做(正如已经评论过的那样),但是对于这种安全的情况,可以重新借用可变的引用:

代码语言:javascript
复制
fn write_u32(mut bytes_opt: Option<&mut Vec<u8>>, value: u32) {
    write_u16(bytes_opt.as_mut().map(|x| &mut **x), (value >> 16) as u16);
    write_u16(bytes_opt, value as u16);
}

bytes_opt.as_mut().map(|x| &mut **x)也可以写成match bytes_opt { Some(&mut ref mut x) => Some(x), None => None, }。一个漂亮的思维模式(从左到右阅读:&mut-dereference(包含的值),ref mut-and,然后接受一个新的可变引用),但是它有效并避免了所有权问题。

票数 3
EN

Stack Overflow用户

发布于 2015-03-29 21:48:16

错误信息是告诉你关键的事情:

bytes_opt搬到这里是因为它的类型是core::option::Option<&mut collections::vec::Vec<u8>>,它是不可复制的。

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

代码语言:javascript
复制
fn write_u16(bytes_opt: Option<&mut Vec<u8>>, value: u16)
//                      ^~~~~~~~~~~~~~~~~~~~

但是,通过使用它,它也消耗了可变的引用。如果您有另一种类型,如Option<u8>Option<&Vec<u8>>,那么编译器就可以为您插入变量的隐式副本。但是,您不允许复制可变引用,因为这样您就会有可更改的别名,因为出于内存安全的原因,编译器不允许这样做。

当您只传递&mut Vec<u8>时,编译器能够跟踪引用并看到一次只有一个项具有引用,因此它允许引用。但是,当可变引用嵌入到另一种类型中时,它无法跟踪。

要使它真正发挥作用,它有点难看,它有比我想要的更多的mut限定符:

代码语言:javascript
复制
fn write_u16(bytes_opt: &mut Option<&mut Vec<u8>>, value: u16) {
    if let Some(ref mut bytes) = *bytes_opt {
        bytes.push((value >> 8) as u8);
        bytes.push(value as u8);
    }
}

fn write_u32(mut bytes_opt: Option<&mut Vec<u8>>, value: u32) {
    write_u16(&mut bytes_opt, (value >> 16) as u16);
    write_u16(&mut bytes_opt, value as u16);
}

在@ChrisMorgan的提示下,我得到了一些符合您最初API的内容:

代码语言:javascript
复制
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);
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29335173

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档