MST

星途 面试题库

面试题:Rust函数中的闭包与所有权

编写一个Rust函数,该函数接收一个闭包作为参数,闭包的参数是一个字符串切片,闭包返回字符串切片的长度。在函数内部调用闭包,并处理好字符串切片的所有权问题,防止出现悬垂指针或内存泄漏。解释闭包捕获变量的三种方式以及在这个场景下的选择原因。
28.4万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
fn call_length_closure<F>(closure: F)
where
    F: Fn(&str) -> usize,
{
    let s = String::from("hello");
    let len = closure(&s);
    println!("Length of the string is: {}", len);
}

闭包捕获变量的三种方式

  1. 按值捕获(move语义):使用move关键字,闭包会获取变量的所有权,将变量从定义处移动到闭包内部。这种方式适用于闭包需要在不同的作用域中使用变量,并且变量在闭包外部不再需要的场景。
  2. 按不可变借用捕获:闭包可以不可变地借用其环境中的变量,当闭包只需要读取变量的值时使用这种方式。在我们的例子中,闭包接受&str作为参数,并没有修改字符串,所以使用这种方式捕获字符串切片。
  3. 按可变借用捕获:闭包可以可变地借用其环境中的变量,允许在闭包内部修改变量的值。当闭包需要修改捕获的变量时使用这种方式。

在这个场景下的选择原因

在这个场景中,闭包接受一个字符串切片&str作为参数,并且只需要返回切片的长度,即仅读取数据而不修改。因此选择按不可变借用捕获的方式,这样既满足闭包读取数据的需求,又避免了不必要的所有权转移,同时防止了悬垂指针或内存泄漏的问题。闭包参数&str指向的字符串切片的所有权仍在调用闭包的函数内(如上述代码中的let s = String::from("hello");s的所有权在call_length_closure函数内),在函数结束时会正常释放内存。