MST

星途 面试题库

面试题:Rust中clone方法与所有权和借用规则的交互

假设有一个包含`Vec<String>`的自定义结构体`MyData { data: Vec<String> }`。编写代码展示如何正确使用`clone`方法来复制这个结构体实例,同时解释在`clone`过程中,`Vec<String>`内部的字符串所有权是如何处理的。如果不使用`clone`,而是尝试通过简单赋值来复制`MyData`实例,会违反Rust的哪些规则,为什么?
46.2万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

代码实现

#[derive(Clone)]
struct MyData {
    data: Vec<String>,
}

fn main() {
    let original = MyData {
        data: vec!["hello".to_string(), "world".to_string()],
    };
    let cloned = original.clone();
    println!("Original data: {:?}", original.data);
    println!("Cloned data: {:?}", cloned.data);
}

clone过程中Vec<String>内部字符串所有权处理

在Rust中,String类型在clone时会进行深拷贝。当对MyData实例调用clone方法时,因为MyData结构体的data字段是Vec<String>clone会遍历Vec中的每个String并调用其clone方法。这意味着每个String内部的堆上数据(字符串内容)都会被复制,originalcloned拥有各自独立的字符串数据,它们在堆上占据不同的内存空间。

不使用clone,简单赋值的情况

如果尝试通过简单赋值来复制MyData实例,例如:

struct MyData {
    data: Vec<String>,
}

fn main() {
    let original = MyData {
        data: vec!["hello".to_string(), "world".to_string()],
    };
    let copied = original; // 这里发生移动
    // println!("Original data: {:?}", original.data); // 这行会报错
    println!("Copied data: {:?}", copied.data);
}

这样做会违反Rust的所有权规则中的独占性规则。在Rust中,当一个变量被赋值给另一个变量时,所有权会发生移动。original将其对data的所有权转移给了copiedoriginal不再拥有对data的有效引用。如果试图访问original.data,编译器会报错,因为original已经被移动,不再拥有合法的内存访问权。这确保了内存安全,防止悬空指针和重复释放内存等问题。