// dictionary
Copyトレイト.
Copyは、値をビット単位で複製するだけで複製が成立することを示す、メソッドを1つも持たないトレイト(マーカートレイト)です1。Copyを実装した型は、代入や関数への受け渡しでムーブではなくコピーが起き、所有権は移らないため元の変数をそのまま使い続けられます。整数型や論理値型をはじめ、プリミティブ型の多くは最初からCopyを実装しています。
#[derive(Copy, Clone)]
struct Price {
yen: u32,
}
fn main() {
let regular = Price { yen: 1200 };
let sale = regular; // ムーブではなくコピーが起きる
println!("通常価格: {}円", regular.yen); // OK: regular はまだ使える
println!("セール価格: {}円", sale.yen);
}Playgroundで開く実装できる型の条件
Copyはどんな型にも付けられるわけではなく、次の2つを両方満たす型だけが実装できます2。
| 条件 | 内容 | 違反時のエラー |
|---|---|---|
全フィールドがCopy |
構造体は全フィールド、列挙型は全バリアントの全フィールドがCopyである必要がある |
E0204 |
Dropを実装していない |
DropとCopyは同時に実装できない |
E0184 |
Dropを実装する型は自身のサイズを超えた資源(ヒープ領域など)を管理しているため、ビットの複製だけでは正しく増やせません1。文字列型やベクタ(Vec)がCopyになれないのはこのためです。
Cloneとの関係と使い分け
.clone()によるクローンを提供するCloneは、Copyのスーパートレイトです(pub trait Copy: Clone)。そのためCopyを実装する型は必ずCloneも実装する必要があり、derive属性では#[derive(Copy, Clone)]とセットで書くのが定型になっています1。
| 観点 | Copy |
Clone |
|---|---|---|
| 複製の起き方 | 代入・受け渡しで暗黙に | .clone()で明示的に |
| 複製の内容 | ビット単位の複製に固定 | 型ごとに自由に実装できる |
| 主な対象 | ヒープを使わない小さな値 | ヒープなどの資源を持つ型 |
小さくヒープを持たない型にはCopyを付けてコピーを気にせず扱えるようにし、資源を持つ型はCopyにできないので必要な場面だけ.clone()します。読み取りたいだけなら、どちらでもなく参照で借用するほうが安価です。
補足
条件を満たさない型に付けるとどうなるか
Copyでないフィールドを持つ型に付けるとE0204になります。
#[derive(Copy, Clone)] // エラー: E0204(Copyでないフィールドを含む)
struct Cart {
items: Vec<String>, // Vec は Copy ではない
}
fn main() {
let cart = Cart { items: vec![String::from("りんご")] };
println!("商品数: {}", cart.items.len());
}Playgroundで開くDropを実装している型に付けるとE0184になります。
#[derive(Copy, Clone)] // エラー: E0184(DropとCopyは同時に実装できない)
struct Receipt {
id: u32,
}
impl Drop for Receipt {
fn drop(&mut self) {
println!("レシート{}を破棄しました", self.id);
}
}
fn main() {
let _receipt = Receipt { id: 1 };
}Playgroundで開く自動でCopyになる型と、参照の扱い
共有参照&Tは、TがCopyかどうかに関わらず常にCopyです1。一方で排他参照&mut TはCopyではありません(コピーできてしまうと、同じ値への排他参照が同時に複数存在することになるためです)。
このほか、Copyな型だけからなるタプル型や関数ポインタなど、自分でderiveしなくてもコンパイラがCopyを実装する型もあります2。
ムーブとコピーはどこが違うのか
実行時の動作としては、ムーブもコピーもメモリ上でビットが複製されることがあり(最適化で消えることもあります)、機械語のレベルでは同じ処理になり得ます。両者の本質的な違いは「複製したあとに元の値へアクセスしてよいかどうか」という、コンパイラが課す規則の側にあります1。
Footnotes
この辞書が使われているページ
backlinks 8