MST

星途 面试题库

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

考虑如下代码片段: ```rust fn main() { let mut vec1 = vec![1, 2, 3]; let vec2 = vec1.clone(); let ref1 = &vec1; vec1.push(4); println!("{:?}", vec2); } ``` 解释这段代码为何能编译通过(或不能通过,如果存在编译问题),阐述`clone`方法在此过程中对所有权和借用规则的遵循和影响。如果要使`vec2`在`vec1`修改后也能反映出变化,应如何修改代码(不改变整体逻辑结构,仅考虑使用合适的Rust特性)。
33.8万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
  1. 代码编译通过原因
    • Rust 有严格的所有权和借用规则。在这段代码中,vec1.clone() 创建了 vec1 的一个新的独立副本 vec2clone 方法会深度复制 vec1 中的所有元素到 vec2,这意味着 vec2 有自己独立的内存空间来存储这些元素。
    • 接着 let ref1 = &vec1; 创建了对 vec1 的一个不可变引用 ref1。虽然之后 vec1.push(4); 修改了 vec1,但这个修改并不影响 vec2,因为 vec2 是一个独立的副本。同时,由于 vec1mut 可变的,且在创建不可变引用 ref1 后没有再通过 ref1 进行访问,所以对 vec1 的修改也是符合借用规则的,因此代码能编译通过。
  2. clone 方法对所有权和借用规则的遵循和影响
    • 所有权clone 方法创建了一个新的对象(这里是 vec2),它拥有自己独立的所有权,与原始对象 vec1 的所有权相互独立。这意味着修改 vec1 不会影响 vec2 的所有权和数据。
    • 借用规则clone 方法本身并不涉及借用。它只是复制数据并创建新的所有权。在创建 vec2 后,对 vec1 的借用和修改都是符合 Rust 的借用规则的。在修改 vec1 时,没有活跃的可变借用(只有不可变借用 ref1 且之后未使用),所以修改操作合法。
  3. 使 vec2vec1 修改后也能反映出变化的修改方法
    • 可以使用 Rc(引用计数)和 RefCell 来实现。Rc 用于共享所有权,RefCell 用于在运行时检查借用规则,以允许内部可变性。
    use std::cell::RefCell;
    use std::rc::Rc;
    
    fn main() {
        let shared_vec = Rc::new(RefCell::new(vec![1, 2, 3]));
        let vec2 = shared_vec.clone();
        let ref1 = &shared_vec;
        shared_vec.borrow_mut().push(4);
        println!("{:?}", vec2.borrow());
    }
    
    • 在上述代码中,Rc::new(RefCell::new(vec![1, 2, 3])) 创建了一个引用计数的 RefCell 包裹的 Vecvec2 = shared_vec.clone(); 增加了引用计数,使得 vec2shared_vec 共享同一个 Vec 的所有权。shared_vec.borrow_mut().push(4); 通过 RefCellborrow_mut 方法获取可变借用并修改 Vecprintln!("{:?}", vec2.borrow()); 通过 borrow 方法获取不可变借用并打印 Vec 的内容,这样 vec2 就能反映出 vec1 修改后的变化。