MST

星途 面试题库

面试题:Rust所有权机制下的复杂数据结构处理

考虑一个场景,有一个`Vec<Box<dyn Trait>>`类型的向量,其中`trait`定义了一个方法`do_something`。现在要实现一个函数,该函数接收这个向量,对其中每个元素调用`do_something`方法,然后将向量返回,并且整个过程要遵循Rust的所有权机制,避免内存泄漏和悬空指针。请编写相应代码,并详细解释所有权在函数调用前后以及处理过程中的变化。
48.5万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
trait Trait {
    fn do_something(&self);
}

struct ImplementingStruct;

impl Trait for ImplementingStruct {
    fn do_something(&self) {
        println!("Doing something");
    }
}

fn process_vector(vec: Vec<Box<dyn Trait>>) -> Vec<Box<dyn Trait>> {
    for item in &vec {
        item.do_something();
    }
    vec
}

所有权变化解释

  1. 函数调用前
    • 调用者拥有Vec<Box<dyn Trait>>类型向量的所有权。这个向量中的每个Box<dyn Trait>也被调用者所拥有。
  2. 函数调用时
    • 所有权通过值传递的方式转移到process_vector函数中。此时,函数process_vector拥有Vec<Box<dyn Trait>>向量的所有权,调用者不再拥有该向量。
  3. 函数处理过程中
    • for item in &vec循环中,item是对向量中Box<dyn Trait>的不可变借用。这意味着函数可以调用do_something方法,因为该方法只需要不可变借用self。由于是借用,Box<dyn Trait>的所有权仍然属于向量,进而属于process_vector函数。
  4. 函数返回后
    • process_vector函数将向量返回,所有权又转移回调用者。调用者再次拥有Vec<Box<dyn Trait>>向量以及其中每个Box<dyn Trait>的所有权。这种方式确保了没有内存泄漏(因为所有权总是被明确的所有者持有),也避免了悬空指针(因为所有权转移后原所有者不再能访问相应资源)。