MST

星途 面试题库

面试题:Rust中Deref与DerefMut trait在复杂场景下的应用

假设有一个嵌套的结构体层次,其中包含多个实现了Deref trait的结构体。在这种情况下,如何确保在使用DerefMut trait进行可变访问时,遵循Rust的借用规则,避免数据竞争和未定义行为?请结合代码示例说明。
12.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 理解DerefDerefMut
    • Deref允许结构体像引用一样使用,当解引用一个实现了Deref的结构体时,*操作符会自动调用Deref::deref方法。
    • DerefMut则允许对结构体进行可变解引用,*操作符会调用DerefMut::deref_mut方法。
  2. 代码示例
    • 首先定义嵌套的结构体层次:
struct Inner {
    data: i32,
}

struct Middle {
    inner: Inner,
}

struct Outer {
    middle: Middle,
}
  • InnerMiddleOuter实现DerefDerefMut
use std::ops::{Deref, DerefMut};

impl Deref for Inner {
    type Target = i32;
    fn deref(&self) -> &Self::Target {
        &self.data
    }
}

impl DerefMut for Inner {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.data
    }
}

impl Deref for Middle {
    type Target = Inner;
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl DerefMut for Middle {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}

impl Deref for Outer {
    type Target = Middle;
    fn deref(&self) -> &Self::Target {
        &self.middle
    }
}

impl DerefMut for Outer {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.middle
    }
}
  • 使用可变访问:
fn main() {
    let mut outer = Outer {
        middle: Middle {
            inner: Inner {
                data: 42,
            },
        },
    };

    // 可变访问内部数据
    let inner_ref: &mut i32 = &mut *outer;
    *inner_ref = 43;

    println!("{}", outer);
}
  1. 遵循借用规则
    • 在上述代码中,通过DerefMut实现了对嵌套结构体中内部数据的可变访问。Rust的借用规则保证了在任何时刻,要么只能有一个可变引用(可变借用),要么只能有多个不可变引用(不可变借用),但不能同时存在。
    • 例如,如果在获取inner_ref可变引用后,尝试再获取一个对outer的不可变引用,编译器会报错:
fn main() {
    let mut outer = Outer {
        middle: Middle {
            inner: Inner {
                data: 42,
            },
        },
    };

    let inner_ref: &mut i32 = &mut *outer;
    // 下面这行代码会报错,因为已经有了对`outer`的可变引用`inner_ref`
    let outer_ref: &Outer = &outer;
}
  • 编译器会提示类似于“cannot borrow outer as immutable because it is also borrowed as mutable”的错误,从而防止数据竞争和未定义行为。

总结:通过正确实现DerefDerefMut trait,并遵循Rust的借用规则,在嵌套结构体层次中使用DerefMut进行可变访问时可以避免数据竞争和未定义行为。