Rust中的可变按引用传递

康尼克

我正在完成此练习(可变的逐个可变参考),但无法理解结果

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=42ff75b2464a99337b7738fba3597512

#[derive(Debug)]
struct Person {
    name: String,
    age: u32,
}

fn birthday_mutable<'a>(mut person: &'a mut Person, replacement: &'a mut Person) {
    println!("[InFn] Before : Alice {:p} : {:?}, Bob {:p} : {:?}", &person, person, &replacement, replacement);
    person = replacement;
    println!("[InFn] After  : Alice {:p} : {:?}", &person, person);
}

fn main() {
    let mut alice = Person {
        name: String::from("Alice"),
        age: 30,
    };
    let mut bob = Person {
        name: String::from("Bob"),
        age: 20,
    };
   
    println!("[Main] Before : Alice {:p} : {:?}, Bob {:p} : {:?}", &alice, alice, &bob, bob);
    birthday_mutable(&mut alice, &mut bob);
    println!("[Main] After :  Alice {:p} : {:?}, Bob {:p} : {:?}", &alice, alice, &bob, bob);
}

在Birthday_mutable函数中,人员处于可变变量中。我们要做的第一件事是人=替换;。这将更改我们的人员变量所指向的内容,并且完全不会修改引用所指向的原始值。

尽管更改了人指向的内容,但结果是

[Main] Before : Alice 0x7ffd0c9b77e0 : Person { name: "Alice", age: 30 }, Bob 0x7ffd0c9b7820 : Person { name: "Bob", age: 20 }
[InFn] Before : Alice 0x7ffd0c9b7568 : Person { name: "Alice", age: 30 }, Bob 0x7ffd0c9b7570 : Person { name: "Bob", age: 20 }
[InFn] After  : Alice 0x7ffd0c9b7568 : Person { name: "Bob", age: 20 }
[Main] After :  Alice 0x7ffd0c9b77e0 : Person { name: "Alice", age: 30 }, Bob 0x7ffd0c9b7820 : Person { name: "Bob", age: 20 }

根据我的理解,结果不应该是这样吗?

[Main] Before : Alice 0x7ffd0c9b77e0 : Person { name: "Alice", age: 30 }, Bob 0x7ffd0c9b7820 : Person { name: "Bob", age: 20 }
[InFn] Before : Alice 0x7ffd0c9b7568 : Person { name: "Alice", age: 30 }, Bob 0x7ffd0c9b7570 : Person { name: "Bob", age: 20 }
[InFn] After  : Alice 0x7ffd0c9b7568 : Person { name: "Bob", age: 20 }
[Main] After :  Alice 0x7ffd0c9b77e0 : Person { name: "Bob", age: 20 } , Bob 0x7ffd0c9b7820 : Person { name: "Bob", age: 20 }

有人可以解释为什么吗?

与一个

输入时,堆栈状态的简化图为birthday_mutable

---- main ----
0x820 bob          = Person { name: "Bob",   age: 20 }
0x7e0 alice        = Person { name: "Alice", age: 30 }

---- birthday_mutable ---
0x570 replacement  = 0x820
0x568 person       = 0x7e0

让我们命名以下突变AB

fn birthday_mutable<'a>(mut person: &'a mut Person, replacement: &'a mut Person) {
                        ^^^A            ^^^B
  • 变异A仅更新存储在address处的内容0x568,因此仅影响引用birthday_mutableperson参数所保存的内容-因为参数是其函数的局部参数(即address0x568birthday_mutable的堆栈帧中),所以此变异不会影响调用者。这是您在这里所做的:

    person = replacement;
    

    执行完上述语句后,地址处的内存0x568包含该值0x820(因此,birthday_mutable'sperson参数现在指的是bob)-您可以通过检查&*person而不是来查看此&person,即,person所指的地址,而不是其person自身所存储的地址


  • 突变B只会更新存储在person参数中所保存地址上的内容,也就是说,它会突变person参数所引用的数据(即,alicemain堆栈框架中)。它是通过person在分配过程中显式取消引用参数来实现的

    *person = Person { name: "Charlie".to_owned(), age: 10 };
    

与某些其他系统语言相比,Rust使他们更容易忘记这些细微差别,因为它会在函数调用和字段访问中自动执行反强制不过,最好记住引擎盖下发生的事情。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章