MST

星途 面试题库

面试题:Rust内存模型中所有权与借用的兼容性基础问题

在Rust中,当我们有一个函数接受一个借用的参数,例如`fn print_name(name: &str)`,请解释在调用这个函数时,对于传递的参数的所有权和借用规则有哪些要求,以确保符合Rust内存模型的兼容性?如果参数是一个自定义结构体的引用,又需要额外注意什么?
11.7万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

对于 &str 参数

  1. 所有权
    • 调用函数时传递的 &str 类型参数不转移所有权。&str 是字符串切片,它指向某个字符串数据,该数据的所有权仍归原始所有者。例如:
    fn print_name(name: &str) {
        println!("Name: {}", name);
    }
    fn main() {
        let s = String::from("Alice");
        print_name(&s);
        // 这里 s 的所有权未改变,仍可继续使用 s
        println!("After function call: {}", s);
    }
    
  2. 借用规则
    • 必须遵循Rust的借用规则。在同一作用域内,不能同时存在可变借用和不可变借用。例如:
    fn main() {
        let mut s = String::from("Bob");
        let r1 = &s;
        // 下面这行代码会报错,因为 r1 是不可变借用,在 r1 有效的作用域内不能有可变借用
        // let r2 = &mut s;
        print_name(r1);
    }
    
    • 借用的生命周期必须足够长,要长于函数调用期间对借用的使用。例如:
    fn main() {
        let name;
        {
            let s = String::from("Charlie");
            name = &s;
        }
        // 这里会报错,因为 s 的生命周期在花括号结束时就结束了,而 name 试图在 s 生命周期结束后使用它
        // print_name(name);
    }
    

对于自定义结构体引用参数

  1. 额外所有权考虑:与 &str 类似,传递自定义结构体的引用时,结构体的所有权不转移。例如:
    struct Person {
        name: String,
        age: u8
    }
    fn print_person(p: &Person) {
        println!("Name: {}, Age: {}", p.name, p.age);
    }
    fn main() {
        let p = Person { name: String::from("David"), age: 30 };
        print_person(&p);
        // p 的所有权未改变,可继续使用 p
    }
    
  2. 额外借用规则
    • 如果结构体中有可变字段,在借用结构体时要注意借用规则。例如:
    struct Counter {
        value: u32
    }
    fn increment(c: &mut Counter) {
        c.value += 1;
    }
    fn main() {
        let mut counter = Counter { value: 0 };
        increment(&mut counter);
        // 同一时间只能有一个可变借用,在可变借用期间不能有不可变借用
        // let r = &counter; // 这行会报错
    }
    
    • 如果结构体包含其他具有复杂生命周期的类型(如引用类型),要确保所有相关的生命周期都能正确匹配。例如:
    struct Data<'a> {
        ref_value: &'a i32
    }
    fn print_data(d: &Data<'_>) {
        println!("Value: {}", d.ref_value);
    }
    fn main() {
        let num = 42;
        let data = Data { ref_value: &num };
        print_data(&data);
    }
    
    这里 Data 结构体中的 ref_value 引用的生命周期必须与传递给 print_data 函数的 Data 结构体引用的生命周期相匹配。