用另一种数据结构在Rust中初始化数据结构的字段

问题描述

我最近开始在Rust中编程,现在想创建一个结构,我想使用其他结构来分配这些字段。在我正在使用的代码库中,有以下示例:

pub struct StType1 {
    f1: String,f2: bool,f3: usize,}

pub struct StType2 {
    // ...
    field1: StType1,// ...
}

impl StType2 {

    // ...

    pub fn build(mut self) {

        // ...

        let st = StType3 {
            field1: self.field1,};

        // ...

    }


    pub fn field1(&self) -> &StType1 {
        &self.field1
    }
}

struct StType3 {

   field1: StType1,// ...

}

StType1 是字段的类型,同时包含在 StType2 StType3 结构中。 StType2 在运行 build()函数时会创建 StType3 ,并且它们应具有与 field1 相同的值。

代码中没有动静,并且在此分配field1: self.field1;中似乎没有副本。为什么?那会发生什么?

之所以问是因为,当我尝试创建类似于 StType3 - ObjType -该文件外部的结构时,

let object1 = StType2::new(...);
let object2 = ObjType {
            field1: object1.field1().clone(),}

在我的函数中,我在 clone()之后获得了对StType1的引用,而不是一个对象,并且在执行此操作时:

let object1 = StType2::new(...);
let object2 = ObjType {
            field1: *object1.field1().clone(),}

我收到一个错误Can't move

发生移动是因为值具有类型 StType1, 没有实现copy特质

我通过添加 StType1 #[derive(Clone)]解决此问题。但是它以前可以与 StType2 一起使用,而无需使用#[derive(Clone)]。为什么现在要添加它?为什么在 StType2 field1 中创建了 StType3 时, field1 没有发生移动(或不需要克隆)的原因strong>已初始化?

解决方法

此代码中没有动静,并且在此分配field1: self.field1中似乎没有副本。为什么?那会发生什么?

这是不正确的–此处有 个移动,因为Rust默认情况下会移动。

这是可能的,因为在上面的声明中:

pub fn build(mut self) {

&之前没有self,因此此build方法仅需self即可。

相反,以下方法:

pub fn field1(&self) -> &StType1 {
    &self.field1
}

获取&self(即参考),然后返回&StType1(另一个参考)。因此,要获得一个StType1来构造您的对象,您需要通过调用.clone()使其拥有。但这仅在StType1实现Clone的情况下有效,这就是为什么您必须向其中添加#[derive(Clone)]的原因。

或者,您也可以将field1()方法更改为也可以通过移动self

pub fn field1(self) -> StType1 {
    self.field1
}

此方法的缺点是,由于它消耗self,即整个结构,因此调用后将无法访问其他任何字段。