部分的ムーブ

Within the destructuring of a single variable, both by-move and by-reference pattern bindings can be used at the same time. Doing this will result in a partial move of the variable, which means that parts of the variable will be moved while other parts stay. In such a case, the parent variable cannot be used afterwards as a whole, however the parts that are only referenced (and not moved) can still be used. Note that types that implement the Drop trait cannot be partially moved from, because its drop method would use it afterwards as a whole.

fn main() {
    #[derive(Debug)]
    struct Person {
        name: String,
        age: Box<u8>,
    }

    // Error! cannot move out of a type which implements the `Drop` trait
    //impl Drop for Person {
    //    fn drop(&mut self) {
    //        println!("Dropping the person struct {:?}", self)
    //    }
    //}
    // TODO ^ Try uncommenting these lines

    let person = Person {
        name: String::from("Alice"),
        age: Box::new(20),
    };

    // `name` は person からムーブしたが、 `age` は参照されています。
    let Person { name, ref age } = person;

    println!("The person's age is {}", age);

    println!("The person's name is {}", name);

    // エラー!部分的ムーブした値の借用:`person` では部分的ムーブが発生しています。
    //println!("The person struct is {:?}", person);

    // `person` は使用できませんが、
    // `person.age` はムーブしていないので使用できます。
    println!("The person's age from person struct is {}", person.age);
}

この例では、age変数をヒープ上に保持し、部分的ムーブを説明しています。上記コードでrefを削除すると、person.ageの所有権がage変数にムーブされるため、エラーになります。もしもPerson.ageがスタック上に保持されていたら、ageの定義がperson.ageをムーブすることなくデータをコピーするので、refは必須ではないのですが、実際にはヒープ上に保持されているためrefは必須です。

参照

デストラクト