Rust高级面试题:解析与示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何通过Rust面试:顶级高级问题



Rust——最受欢迎的系统编程语言之一,对高级开发者的需求持续增长。如果你已经掌握了基本语法和所有权系统,面试中等待你的将是考察对unsafe代码、异步、复杂生命周期和元编程深入理解的问题。在本文中,我们将分析关键主题并提供代码示例,帮助你自信地通过面试。



1. Unsafe Rust:何时以及为何使用?



高级面试中最常见的问题之一:“解释一下你何时会使用unsafe,以及这会违反哪些保证”。



答案应包括unsafe提供的四个主要能力:



  • 解引用裸指针(*const T 和 *mut T)
  • 调用unsafe函数(例如FFI)
  • 访问可变静态变量
  • 实现unsafe trait


示例:实现一个手动管理内存的简单动态数组。



use std::alloc::{alloc, dealloc, Layout};use std::ptr;

struct MyVec { ptr: *mut i32, len: usize, cap: usize,}

impl MyVec { fn new() -> Self { MyVec { ptr: ptr::null_mut(), len: 0, cap: 0, } }

fn push(&mut self, val: i32) { if self.len == self.cap { let new_cap = if self.cap == 0 { 1 } else { self.cap * 2 }; let new_layout = Layout::array::<i32>(new_cap).unwrap(); let new_ptr = unsafe { alloc(new_layout) as *mut i32 }; // 复制旧数据 unsafe { ptr::copy_nonoverlapping(self.ptr, new_ptr, self.len); if !self.ptr.is_null() { let old_layout = Layout::array::<i32>(self.cap).unwrap(); dealloc(self.ptr as *mut u8, old_layout); } } self.ptr = new_ptr; self.cap = new_cap; } unsafe { ptr::write(self.ptr.add(self.len), val); } self.len += 1; }}

impl Drop for MyVec { fn drop(&mut self) { if !self.ptr.is_null() { unsafe { let layout = Layout::array::<i32>(self.cap).unwrap(); dealloc(self.ptr as *mut u8, layout); } } }}


建议:始终强调unsafe不是禁用检查,而是承担起维护不变量的责任。



2. 生命周期与变型:编译器如何检查引用



在高级水平,你会被要求解释什么是变型(协变、逆变、不变)在生命周期上下文中的含义。这是理解某些类型无法编译的关键。



  • 协变:&'a T——如果'a大于'b,则&'a T可以用作&'b T。
  • 逆变:fn(T)——如果'a大于'b,则fn(&'b T)可以用作fn(&'a T)。
  • 不变:&mut T——生命周期必须完全匹配。


示例:为什么以下代码无法编译?



fn foo<'a>(x: &'a mut &'a str, y: &'a str) {    *x = y;}

fn main() { let mut s = "hello"; let r = &s; foo(&mut s, r); // 错误!}


答案:&mut T在T上是不变的,因此内部引用的生命周期必须与外部引用的生命周期完全一致。编译器无法“压缩”r的生命周期。



3. Async Rust:Pin、Unpin 与 Future

博客

书籍推荐