MST

星途 面试题库

面试题:Rust中move关键字在闭包中如何影响所有权转移

请举例说明在Rust中,当闭包捕获外部变量时,move关键字是怎样改变变量所有权转移的。并解释在以下代码场景中,使用move关键字和不使用move关键字的区别: ```rust fn main() { let s = String::from("hello"); let closure = || println!("{}", s); // 在这里添加使用move关键字和不使用move关键字的两种情况分别进行分析 } ```
18.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

不使用 move 关键字的情况

  1. 所有权分析
    • 在这段代码let closure = || println!("{}", s);中,闭包closure捕获了变量s,但此时并没有转移s的所有权。
    • 闭包默认以借用的方式捕获外部变量。这里闭包捕获s为不可变借用,因为println!只是读取s的内容。
    • 由于闭包只是借用s,所以在闭包之后,s仍然可以被使用。例如,如果在闭包定义之后添加println!("{}", s);,代码依然可以正常编译和运行,因为s的所有权还在原来的作用域。
  2. 代码示例
fn main() {
    let s = String::from("hello");
    let closure = || println!("{}", s);
    closure();
    println!("{}", s);
}
  • 上述代码会依次打印hello两次,证明s的所有权未转移,在闭包调用后仍然可以使用。

使用 move 关键字的情况

  1. 所有权分析
    • 当使用move关键字,即let closure = move || println!("{}", s);时,闭包会获取s的所有权。
    • move关键字强制闭包获取它所捕获变量的所有权,而不是借用。这意味着变量s的所有权从定义它的作用域转移到了闭包中。
    • 一旦所有权转移到闭包,在闭包外部就不能再使用s。例如,如果在闭包定义之后添加println!("{}", s);,代码将无法编译,会报错提示s已被移动。
  2. 代码示例
fn main() {
    let s = String::from("hello");
    let closure = move || println!("{}", s);
    // println!("{}", s); // 这行代码会报错,因为s的所有权已被闭包move走
    closure();
}
  • 上述代码中,取消注释println!("{}", s);会导致编译错误,提示s已被移动。而闭包closure可以正常调用并打印hello,因为它拥有了s的所有权。