クローン

メモリ上の資源を扱う際、変数束縛や関数呼び出しを介して移動させるのがデフォルトの挙動です。しかしながら、場合によっては資源のコピーを作るのが適切なこともあります。

Cloneトレイトはまさにこのためにあります。普通はCloneトレイトで定義されている.clone()を用います。

// いかなる資源も持たない構造体
#[derive(Debug, Clone, Copy)]
struct Unit;

// `Clone`トレイトを実装する型の変数を資源として持つタプル
#[derive(Clone, Debug)]
struct Pair(Box<i32>, Box<i32>);

fn main() {
    // `Unit`のインスタンスを作成。
    let unit = Unit;
    // `Unit`をコピー、移動させる資源は存在しません。
    let copied_unit = unit;

    // いずれの`Unit`も独立に使用できます。
    println!("original: {:?}", unit);
    println!("copy: {:?}", copied_unit);

    // `Pair`のインスタンスを作成。
    let pair = Pair(Box::new(1), Box::new(2));
    println!("original: {:?}", pair);

    // `pair`を`moved_pair`に移動、資源は移動します。
    let moved_pair = pair;
    println!("moved: {:?}", moved_pair);

    // エラー!`pair`は資源を失っています。
    //println!("original: {:?}", pair);
    // TODO ^ この行をアンコメントしてみましょう。

    // `moved_pair`を`cloned_pair`にクローンします。(資源もクローンされます。)
    let cloned_pair = moved_pair.clone();
    // std::mem::dropを用いて元のpairをドロップします。
    drop(moved_pair);

    // エラー!`moved_pair`はドロップされています。
    //println!("moved and dropped: {:?}", moved_pair);
    // TODO ^ この行をアンコメントしてみましょう。

    // .clone()した値はまだ使用可能!
    println!("clone: {:?}", cloned_pair);
}