から 本 :
タイプまたはその一部が
Copy
トレイトを実装している場合、RustではタイプにDrop
トレイトで注釈を付けることはできません。値がスコープ外になったときに型に何か特別なことが必要で、その型にCopy
アノテーションを追加すると、コンパイル時エラーが発生します。
同じタイプでCopy
とDrop
を許可しないように設計が決定されたのはなぜですか?
Drop
トレイトは、 [〜#〜] raii [〜#〜] コンテキストで使用されます。通常、オブジェクトが破棄されたときにリソースを解放/閉じる必要がある場合に使用されます。Copy
型は、memcpy
でのみコピーできる簡単な型です。これらの2つの説明により、それらが排他的であることがより明確になります。重要なデータをmemcpy
することは意味がありません。データをコピーし、コピーの1つを削除するとどうなりますか?他のコピーの内部リソースは信頼できなくなります。
実際、Copy
は、関数を定義しないという点で、「実際の」特性でさえありません。これは、コンパイラに「単純なバイトコピーで自分自身を複製できます」と言う特別なマーカーです。したがって、実装がまったくないため、Copy
のカスタム実装を提供することはできません。ただし、タイプをコピー可能としてマークすることはできます。
impl Copy for Foo {}
以上、派生:
#[derive(Clone, Copy)]
struct Foo { /* ... */ }
これは、すべてのフィールドがCopy
を実装している場合にのみビルドされます。それ以外の場合、これは安全ではないため、コンパイラはコンパイルを拒否します。
例として、File
構造体がCopy
を実装していると仮定しましょう。もちろん、これはnotの場合であり、この例は間違っており、コンパイルできません。
fn drop_copy_type<T>(T x)
where
T: Copy + Drop,
{
// The inner file descriptor is closed there:
std::mem::drop(x);
}
fn main() {
let mut file = File::open("foo.txt").unwrap();
drop_copy_type(file);
let mut contents = String::new();
// Oops, this is unsafe!
// We try to read an already closed file descriptor:
file.read_to_string(&mut contents).unwrap();
}
ドキュメント を引用します。
[...] [A]
Drop
を実装するタイプはCopy
にすることはできません。これは、独自のリソース以外のリソースを管理しているためですsize_of::<T>
バイト。