MST
星途 面试题库

面试题:Rust结构体移动语义对复杂数据结构内存管理的影响

考虑以下嵌套结构体的Rust代码: ```rust struct Inner { value: i32 } struct Outer { inner: Inner, other_data: Vec<String> } fn process_outer(outer: Outer) -> Outer { let Inner { value } = outer.inner; // 这里如果想要创建一个新的Outer结构体,包含修改后的Inner,并且保证内存管理正确,代码应该怎么写?详细说明每一步的移动语义和内存管理操作。 Outer { inner: Inner { value: value + 1 }, other_data: outer.other_data } } ```
45.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 移动语义和内存管理分析
    • 首先,fn process_outer(outer: Outer) 函数通过值传递接收 outer 变量。这意味着 outer 的所有权被转移到函数内部。
    • let Inner { value } = outer.inner; 这一行代码从 outer 中取出 inner 结构体,并解构出 value 字段。此时,outer.inner 的所有权被转移到 value 变量(严格来说是 Inner 结构体的成员被逐一移动到新的绑定中),outer 中的 inner 字段现在处于 “已移动” 状态,不能再被使用。
  2. 创建新的 Outer 结构体
    • Outer { inner: Inner { value: value + 1 }, other_data: outer.other_data }
      • 新的 Inner 结构体创建:Inner { value: value + 1 } 创建了一个新的 Inner 结构体实例,其 value 字段是原 value 加1。这里新的 Inner 结构体在栈上分配内存(因为 Inner 是一个简单的结构体,其成员 valuei32,是一个固定大小的类型)。
      • other_data: outer.other_dataouter.other_data 的所有权被转移到新创建的 Outer 结构体中。Vec<String> 类型的数据存储在堆上,通过所有权转移,新的 Outer 结构体现在负责管理这块堆内存。
    • 函数返回新创建的 Outer 结构体,其所有权被转移出函数,调用者现在拥有这个新的 Outer 结构体实例,并负责管理其内存。当调用者的作用域结束时,Outer 结构体的析构函数会被调用,它会首先调用 other_data 成员(Vec<String>)的析构函数来释放堆上的字符串数据,然后 Inner 结构体的析构函数会被调用(由于 Inner 只有简单类型 i32,其析构函数为空操作),从而完成整个内存管理过程。

代码实现如下:

struct Inner {
    value: i32
}

struct Outer {
    inner: Inner,
    other_data: Vec<String>
}

fn process_outer(outer: Outer) -> Outer {
    let Inner { value } = outer.inner;
    Outer {
        inner: Inner {
            value: value + 1
        },
        other_data: outer.other_data
    }
}

这样,代码通过移动语义和正确的内存管理,创建了一个新的 Outer 结构体,其中 Inner 结构体的 value 字段增加了1。