MST
星途 面试题库

面试题:Rust结构体移动语义与借用规则的交互

假设你有一个结构体`MyStruct`,其中包含一个`Vec<i32>`类型的成员。编写一段代码,展示如何在遵循Rust借用规则的前提下,通过移动语义来安全地复用这个结构体中的数据,并且解释在这个过程中编译器是如何保证内存安全的。
22.0万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
struct MyStruct {
    data: Vec<i32>,
}

impl MyStruct {
    fn consume_and_reuse(self) -> Vec<i32> {
        self.data
    }
}

fn main() {
    let mut my_struct = MyStruct { data: vec![1, 2, 3] };
    let reused_data = my_struct.consume_and_reuse();
    // 这里my_struct已经被移动,不能再使用,例如下面这行代码会报错:
    // println!("{:?}", my_struct);
    println!("Reused data: {:?}", reused_data);
}

解释

  1. 移动语义:在Rust中,当一个值被移动时,源变量的所有权被转移到目标变量。在MyStructconsume_and_reuse方法中,self是按值传递的,这意味着MyStruct实例的所有权被转移到方法内部。方法返回self.datadata的所有权被移动出MyStruct实例并返回给调用者。
  2. 编译器保证内存安全
    • 所有权系统:Rust的所有权系统确保每个值有且只有一个所有者。当my_struct调用consume_and_reuse方法时,my_struct失去对data的所有权,因此后续不能再使用my_struct。如果尝试使用已被移动的my_struct,编译器会报错,从而防止悬空指针和数据竞争。
    • 内存释放:当MyStruct实例的所有权被转移时,Rust的所有权系统会确保在MyStruct实例离开作用域时,其占用的内存(包括Vec<i32>占用的内存)会被正确释放。由于Vec<i32>实现了Drop trait,当Vec<i32>的所有权被转移或者离开作用域时,其内部的内存会被自动释放,保证了内存安全。