コピーや複製はRustでは、オブジェクトの型に依存してデフォルトで実装されているもの(プリミティブ型)もありますが、性能を重視しているので基本は移動です。
代入のセマンティクには以下の三種類がありますが、
① 共有:本体は共有してアクセスポインタは個別に持つやり方、GCを持つ言語(Java, C#, Golang)では標準のようです
② コピー:C++のデフォルト実装が該当
③ 移動:Rustの標準、ただしプリミティブ型(オブジェクトの長さが変化しないのでスタックを使用する型)は例外
Rustでプリミティブ型以外のヒープ領域に保存されるオブジェクトは標準は移動ですが、コピー(コピーすることに意味があれば、DBのコネクションとかコピーは無意味だし害があるだろう)はcloneを実装すれば良いのですが、例えば構造体などはデフォルトでcloneを適用しようとしても、対象オブジェクトのメンバーは対象に含まれないからコンパイルは通りません。
以下のコードはコンパイルエラーになりますが、理由はderiveは構造体という型に適用されるだけで、その要素であるVec型には適用されないから。
回避方法は、以下のソースでコメントアウトしているCloneのカスタマイズが必要になります。
| #[derive(Copy, Clone)]
| ^^^^
| struct S {
| x: Vec,
| ----------- this field does not implement `Copy`
fn main() {
#[derive(Copy, Clone)]
struct S {
x: Vec<i32>,
}
/*impl Clone for S {
fn clone(&self) -> Self {
S { x: self.x.clone() }
}
}*/
let mut s1 = S { x: vec![12] };
let s2 = s1.clone();
s1.x[0] += 1;
print!("{} {}", s1.x[0], s2.x[0]);
//
// same as above(this field(x: Vec) does not implement `Copy`)
// Object members are out of target, Copy/Clone is applied only to struct S/S1
//
struct S1 {
x: Vec<i32>,
}
impl Copy for S1 {}
impl Clone for S1 {
fn clone(&self) -> Self {
*self
}
}
}
この辺りについては、
https://doc.rust-lang.org/std/marker/trait.Copy.html
の解説を読むのが良いと思います。
admin