Copy型
ムーブセマンティクスがデフォルトですが、特定の型はデフォルトでコピーされます。
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 fn main() { let x = 42; let y = x; dbg!(x); // Copy でなければアクセスできない dbg!(y); }
これらの型は Copy トレイトを実装しています。
自分で定義した型でも、コピーセマンティクスを使うようにオプトインできます。
// Copyright 2023 Google LLC // SPDX-License-Identifier: Apache-2.0 #[derive(Copy, Clone, Debug)] struct Point(i32, i32); fn main() { let p1 = Point(3, 4); let p2 = p1; println!("p1: {p1:?}"); println!("p2: {p2:?}"); }
- 代入後、
p1とp2はどちらもそれぞれのデータを所有します。 - また、
p1.clone()を使ってデータを明示的にコピーすることもできます。
コピーとクローンは同じものではありません。
- コピーはメモリ領域のビット単位の複製を指し、任意のオブジェクトに対して機能するわけではありません。
- コピーではカスタムロジックを入れられません(C++ のコピーコンストラクタとは異なります)。
- クローンはより一般的な操作であり、
Cloneトレイトを実装することでカスタムな振る舞いも可能です。 - コピーは
Dropトレイトを実装している型では機能しません。
上の例で、次を試してください。
struct PointにStringフィールドを追加します。StringはCopy型ではないため、コンパイルできなくなります。derive属性からCopyを削除します。すると、コンパイラエラーはp1のprintln!で発生します。- 代わりに
p1をクローンすると動作することを確認します。
さらに詳しく
- 共有参照は
Copy/Cloneですが、可変参照はそうではありません。これは、Rust が可変参照に排他性を要求するためです。したがって、共有参照のコピーを作るのは有効ですが、可変参照のコピーを作ると Rust の借用規則に違反します。