MST

星途 面试题库

面试题:Rust堆内存优化之所有权转移

假设有一个复杂的数据结构,其中包含多个嵌套的自定义类型,且部分数据存储在堆上。在函数间传递这个数据结构时,如何通过合理的所有权转移和借用规则来优化堆内存的使用,避免不必要的复制?请给出具体代码示例并解释。
25.9万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

Rust 示例

// 定义自定义类型
struct Inner {
    data: String,
}

struct Outer {
    inner: Inner,
}

// 函数接受所有权并转移
fn take_ownership(outer: Outer) {
    println!("Received Outer with data: {}", outer.inner.data);
}

// 函数借用
fn borrow_outer(outer: &Outer) {
    println!("Borrowed Outer with data: {}", outer.inner.data);
}

解释

  1. 所有权转移:在 take_ownership 函数中,outer 参数接受 Outer 实例的所有权。这意味着调用该函数后,原变量不再拥有该实例,从而避免了不必要的复制。这种方式适合于调用函数后原变量不再使用该数据的场景。
  2. 借用:在 borrow_outer 函数中,outer 参数是对 Outer 实例的借用。通过使用 & 符号,函数可以访问数据而不获取所有权,这样原变量仍然拥有该实例。这种方式适用于函数只需要读取数据,而调用者后续还需要使用该数据的场景。

C++ 示例

#include <iostream>
#include <memory>

// 定义自定义类型
struct Inner {
    std::string data;
    Inner(const std::string& d) : data(d) {}
};

struct Outer {
    std::unique_ptr<Inner> inner;
    Outer(const std::string& d) : inner(std::make_unique<Inner>(d)) {}
};

// 函数接受所有权并转移
void take_ownership(Outer outer) {
    std::cout << "Received Outer with data: " << outer.inner->data << std::endl;
}

// 函数借用
void borrow_outer(const Outer& outer) {
    std::cout << "Borrowed Outer with data: " << outer.inner->data << std::endl;
}

解释

  1. 所有权转移:在 C++ 中,std::unique_ptr 用于管理堆上的对象,具有唯一所有权。take_ownership 函数通过值传递 Outer 实例,会导致 Outer 实例中的 std::unique_ptr<Inner> 的所有权被转移到函数中。这避免了数据的复制,因为 std::unique_ptr 转移所有权时只是移动内部指针。
  2. 借用borrow_outer 函数通过 const Outer& 接受 Outer 实例的引用,这样函数可以访问 Outer 实例及其内部数据,但不会获取所有权。这种方式适用于函数只需要读取数据,而调用者后续还需要使用该数据的场景,避免了不必要的复制。