MST

星途 面试题库

面试题:Rust中所有权转移在函数调用场景下如何保障内存安全

请描述在Rust中,当一个函数接受一个拥有所有权的变量作为参数时,所有权是如何转移的,以及这种转移机制怎样保障内存安全。举例说明函数调用前后变量的所有权状态变化。
17.8万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 所有权转移机制

    • 在Rust中,当一个函数接受一个拥有所有权的变量作为参数时,所有权会从调用者转移到被调用函数。这是Rust所有权系统的核心特性之一。例如,假设有一个函数take_ownership接受一个字符串String类型的参数:
    fn take_ownership(s: String) {
        println!("Function has taken ownership of: {}", s);
    }
    
    • 当我们在另一个函数中调用take_ownership时:
    fn main() {
        let s = String::from("hello");
        take_ownership(s);
        // 这里如果尝试使用`s`会报错,因为所有权已经转移
        // println!("s: {}", s); // 这行会导致编译错误,因为`s`的所有权已经被take_ownership函数拿走
    }
    
    • take_ownership函数结束时,这个String对象所占用的内存会被释放,因为函数拥有这个对象的所有权。
  2. 保障内存安全

    • Rust的所有权转移机制保障内存安全主要通过以下几点:
      • 单一所有权:每个值在任何时刻都只有一个所有者。当函数接受所有权后,原变量不再能访问,避免了多个变量同时尝试释放同一内存的情况(双重释放错误)。例如上面例子中,main函数中的s在传递给take_ownership后,不能再使用,防止了main函数后续意外地对已转移所有权的s进行操作导致内存错误。
      • 自动内存管理:当所有者(如上述take_ownership函数)离开作用域时,Rust自动调用drop函数释放其所拥有的值的内存。这确保了内存的及时释放,避免了内存泄漏。例如take_ownership函数结束时,它所拥有的String对象的内存会被释放。
  3. 变量所有权状态变化举例

    • 调用前:在main函数中创建let s = String::from("hello");时,变量s拥有这个字符串的所有权,此时s可以对字符串进行各种操作,如读取、修改(如果是可变引用)。
    • 调用时:当执行take_ownership(s);s的所有权转移给take_ownership函数的参数s(这里函数参数的smain函数中的s是不同的变量,但名字相同只是为了方便说明)。从这一刻起,main函数中的s不再拥有字符串的所有权。
    • 调用后take_ownership函数可以自由操作这个字符串,直到函数结束,字符串的内存被释放。而main函数中的s在函数调用后不能再被使用,因为它已失去所有权。如果尝试使用,编译器会报错,从而保障了内存安全。