具有部分移动错误的结构

Don*_*ein 4 rust

我有一个简单的结构和它的两个实例,如下所示:

#[derive(Debug)]
struct User {
    first: String,
    last: String,
    age: u32,
}

let u1 = User {
    first: String::from("John"),
    last: String::from("Doe"),
    age: 22,
};

let u2 = User {
    first: String::from("Mary"),
    ..u1
};

println!("user: {:#?}", u1);
Run Code Online (Sandbox Code Playgroud)

错误信息:

#[derive(Debug)]
struct User {
    first: String,
    last: String,
    age: u32,
}

let u1 = User {
    first: String::from("John"),
    last: String::from("Doe"),
    age: 22,
};

let u2 = User {
    first: String::from("Mary"),
    ..u1
};

println!("user: {:#?}", u1);
Run Code Online (Sandbox Code Playgroud)

我试图修改它以..&u1希望它能够通过借用检查,以便我可以将基本结构(u1)传播到 u2,但无济于事,想知道我想在这里做什么?

我知道这是因为u1.lastis a String,因此需要传递引用,但我不确定如何使其在这种情况下工作。

Pri*_*six 6

您的User类型包含 type String,它拥有它所拥有的字符串数据(并且不 impl Copy),这就是为什么两个用户不能指向内存中的相同名称的原因。

您可能想要的解决方案:

#[derive(Debug, Clone)]
struct User {
    first: String,
    last: String,
    age: u32,
}

fn main() {
    let u1 = User {
        first: String::from("John"),
        last: String::from("Doe"),
        age: 22,
    };

    let u2 = User {
        first: String::from("Mary"),
        ..u1.clone() // Copy the strings into the new user 
        // (it also copies first, which is then thrown away? Maybe the compiler optimizes this away)
    };

    println!("user: {:#?}", u1);

}
Run Code Online (Sandbox Code Playgroud)

但是如果你真的想让两个用户指向内存中的同一个名字(很确定你没有),有几个选项:

  • 您可以更改String&'static str. 然而,这意味着您必须在编译时指定它。(您不能在运行时在其名称中输入用户类型,并将其存储在用户中)

    #[derive(Debug)]
    struct User {
        first: &'static str,
        last: &'static str,
        age: u32,
    }
    
    fn main() {
        let u1 = User {
            first: "John",
            last: "Doe",
            age: 22,
        };
    
        let u2 = User {
            first: "Mary",
            ..u1
        };
    
        println!("user: {:#?}", u1);
    }
    
    
    Run Code Online (Sandbox Code Playgroud)
    • 您可以使用 aRc来跟踪对一块内存的引用。这样您就不必担心生命周期以及谁拥有什么。(虽然运行时成本很小)
    use std::rc::Rc;
    
    #[derive(Debug, Clone)]
    struct User {
        first: Rc<String>,
        last: Rc<String>,
        age: u32,
    }
    
    fn main() {
        let u1 = User {
            first: Rc::new(String::from("John")),
            last: Rc::new(String::from("Doe")),
            age: 22,
        };
    
        let u2 = User {
            first: Rc::new(String::from("Mary")),
            ..u1.clone() // Clone the references, not the actual string. For strings with just a couple characters, the time difference is completely negligible)
        };
    
        println!("user: {:#?}", u1);
    }
    
    Run Code Online (Sandbox Code Playgroud)
    • Rc<Mutex<String>>如果您想稍后修改名称,并在 u1 和 u2 中更改它,请改用 a 。