Clone and Copy
メモリ上の資源を扱う際、変数束縛や関数呼び出しを介して移動させるのがデフォルトの挙動です。しかしながら、場合によっては資源のコピーを作るのが適切なこともあります。
Cloneトレイトはまさにこのためにあります。普通はCloneトレイトで定義されている.clone()を用います。
Copy: Implicit Cloning
The Copy trait allows a type to be duplicated simply by copying bits, with no additional logic required. When a type implements Copy, assignments and function calls will implicitly copy the value instead of moving it.
Important: Copy requires Clone - any type that implements Copy must also implement Clone. This is because Copy is defined as a subtrait: trait Copy: Clone {}. The Clone implementation for Copy types simply copies the bits.
Not all types can implement Copy. A type can only be Copy if:
- All of its components are
Copy - It doesn’t manage external resources (like heap memory, file handles, etc.)
// A unit struct without resources
// Note: Copy requires Clone, so we must derive both
#[derive(Debug, Clone, Copy)]
struct Unit;
// A tuple struct with resources that implements the `Clone` trait
// This CANNOT be Copy because Box<T> is not Copy
#[derive(Clone, Debug)]
struct Pair(Box<i32>, Box<i32>);
fn main() {
// `Unit`のインスタンスを作成。
let unit = Unit;
// Copy `Unit` - this is an implicit copy, not a move!
// Because Unit implements Copy, the value is duplicated automatically
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);
// Move `pair` into `moved_pair`, moves resources
// Pair does not implement Copy, so this is a move
let moved_pair = pair;
println!("moved: {:?}", moved_pair);
// エラー!`pair`は資源を失っています。
//println!("original: {:?}", pair);
// TODO ^ この行をアンコメントしてみましょう。
// Clone `moved_pair` into `cloned_pair` (resources are included)
// Unlike Copy, Clone is explicit - we must call .clone()
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);
}