std::clone::Cloneトレイト
std::clone::Clone
トレイトを実装した値は、自身のクローンをメモリ上に新たに作ることができる。
以下のような定義となっている。
pub trait Clone: Sized { fn clone(&self) -> Self; fn clone_from(&mut self, source: &Self) { *self = source.clone() } }
clone()
メソッドは、self の独立したコピーを生成し、clone_from()
メソッドは、self を書き換えて source のコピーにする。
Clone
トレイとは Sized
マーカートレイトを拡張しているため、メモリ上におけるサイズが既知な型だけがクローン可能となる。
clone() メソッド
標準ライブラリで定義される型は、コピーして意味のあるものほぼ全てが Clone
を実装している。
独自の型に Clone を実装する場合、型定義の上に #[derive(Clone)]
属性を書くことで、Rust が自動的に Cloneトレイトを実装してくれる。
#[derive(Clone, Debug)] struct Reading<T> { frequency: T, }
型変数 T
はデフォルトで struct Reading<T: Sized>
と解釈されるため、clone()
により芋づる式に値がコピーされ、別の資源として値を取得できる。
let original = Reading {frequency: "xxx"}; let cloned = original.clone(); drop(original); println!("clone: {:?}", cloned);
clone()
はその型が保持する全ての値をコピーすることになるため、高価な処理になる可能性があるため注意して使う必要がある。
clone_from() メソッド
a = b.clone()
を a.clone_from(&b)
と書くことができる。機能的にはどちらも同じだが、a.clone_from(&b)
はリソースを再利用するためのオーバーライドが提供されている可能性がある。
デフォルトの実装では *self = source.clone()
のように source
をクローンして *self
に移動しているだけであるが、例えば String
では以下のように最適化されたオーバーライドが提供されている。
impl Clone for String { fn clone(&self) -> Self { String { vec: self.vec.clone() } } /// Clones the contents of `source` into `self`. /// /// This method is preferred over simply assigning `source.clone()` to `self`, /// as it avoids reallocation if possible. fn clone_from(&mut self, source: &Self) { self.vec.clone_from(&source.vec); } }
String の内部ベクタが、クローン元の内容を保持するのに十分なサイズが確保されていた場合、確保済みのバッファの中身を書き換えるだけでよく、これにより余分なヒープ確保や開放が不要となる。