为什么在函数内部对传递的Option进行突变不会传播到外部的Option?

时间:2018-09-15 11:11:54

标签: rust move-semantics mutability

我已经这样说明了:

fn main() {

    let mut opt1 = Some(1);
    // compiler complains that opt2 doesn't have to be mutable
    let mut opt2 = Some(1);

    fn take_inner(mut opt: Option<u8>) {
        opt.take();
    };

    opt1.take();
    take_inner(opt2);

    println!("opt1 {:?}", opt1); // prints "opt1 None"
    println!("opt2 {:?}", opt2); // prints "opt2 Some(1)"

}

Rust Playground link

为什么在函数内调用opt.take()与在外部调用相对于主函数的作用不同?

2 个答案:

答案 0 :(得分:5)

T: Copy时,Option<T>也是如此。这意味着,当您将其作为函数参数传递时:

take_inner(opt2);

它实际上将复制数据。如果T不是Copy,那么这些值都将无效,因为该值将被移动,因此您以后甚至无法打印。

如果将其作为可变引用传递,则该函数可以更改原始值:

fn take_inner(opt: &mut Option<u8>) {
    opt.take();
};

take_inner(&mut opt2);

答案 1 :(得分:4)

由于u8是副本类型,而Option具有副本类型

impl<T> Copy for Option<T>
where
    T: Copy,

take_inner复制了opt2

您可以通过引用可变内容来解决此问题:

fn main() {
    let mut opt1 = Some(1);
    // compiler complains that opt2 doesn't have to be mutable
    let mut opt2 = Some(1);

    fn take_inner(opt: &mut Option<u8>) {
        opt.take();
    };

    opt1.take();
    take_inner(&mut opt2);

    println!("opt1 {:?}", opt1);
    println!("opt2 {:?}", opt2);
}

Playground link