MST

星途 面试题库

面试题:Rust函数参数传递方式的理解与应用

在Rust中,有哪些常见的函数参数传递方式?请举例说明每种传递方式在所有权和生命周期方面的特点,并解释当函数接受一个结构体作为参数时,不同传递方式对结构体实例的影响。
45.7万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 值传递(Pass by Value)
    • 所有权特点:当使用值传递时,函数获取参数的所有权。这意味着一旦函数调用结束,参数所占用的内存会在函数作用域结束时被释放。
    • 生命周期特点:参数的生命周期在函数结束时终止。
    • 示例
struct Point {
    x: i32,
    y: i32,
}

fn take_ownership(p: Point) {
    println!("Taken ownership of Point: ({}, {})", p.x, p.y);
}

fn main() {
    let my_point = Point { x: 10, y: 20 };
    take_ownership(my_point);
    // 这里不能再使用my_point,因为所有权已转移给take_ownership函数
    // println!("{:?}", my_point); // 这行代码会报错
}
  • 对结构体实例的影响:结构体实例的所有权被转移到函数中,原变量在函数调用后不再有效。
  1. 引用传递(Pass by Reference)
    • 所有权特点:函数不获取参数的所有权,而是借用参数。借用有两种类型:不可变借用(&T)和可变借用(&mut T)。
    • 生命周期特点:借用的生命周期必须满足生命周期规则,即借用的生命周期不能长于被借用对象的生命周期。
    • 不可变引用示例
struct Point {
    x: i32,
    y: i32,
}

fn print_point(p: &Point) {
    println!("Point: ({}, {})", p.x, p.y);
}

fn main() {
    let my_point = Point { x: 10, y: 20 };
    print_point(&my_point);
    // 仍然可以使用my_point,因为所有权未转移
    println!("{:?}", my_point);
}
  • 可变引用示例
struct Point {
    x: i32,
    y: i32,
}

fn modify_point(p: &mut Point) {
    p.x += 1;
    p.y += 1;
}

fn main() {
    let mut my_point = Point { x: 10, y: 20 };
    modify_point(&mut my_point);
    println!("{:?}", my_point);
}
  • 对结构体实例的影响:不可变引用允许函数读取结构体实例的内容,但不能修改。可变引用允许函数修改结构体实例的内容,而不会转移所有权,原变量在函数调用后仍然有效。
  1. 移动语义(Move Semantics)类似值传递但强调所有权转移本质
    • 所有权特点:同值传递,所有权从调用者转移到被调用函数。这在Rust中是默认行为,尤其在涉及堆分配数据时。例如,String类型的数据。
    • 生命周期特点:参数的生命周期在函数结束时终止。
    • 示例
fn print_string(s: String) {
    println!("String: {}", s);
}

fn main() {
    let my_string = String::from("Hello");
    print_string(my_string);
    // 这里不能再使用my_string,因为所有权已转移
    // println!("{}", my_string); // 这行代码会报错
}
  • 对结构体实例的影响:如果结构体中包含像String这样具有移动语义的成员,当结构体实例通过值传递(移动)给函数时,其内部成员的所有权也会转移,原结构体实例在函数调用后不再有效。