从the book开始:
如果一个类型或其任何部分实现了
Drop
特征,Rust将不允许我们用Copy
特征对该类型进行注释.如果该类型在值超出范围时需要发生特殊情况,并且我们向该类型添加了Copy
注释,那么我们将得到一个编译时错误.
为什么设计决定不允许在同一型号上使用Copy
和Drop
?
从the book开始:
如果一个类型或其任何部分实现了
Drop
特征,Rust将不允许我们用Copy
特征对该类型进行注释.如果该类型在值超出范围时需要发生特殊情况,并且我们向该类型添加了Copy
注释,那么我们将得到一个编译时错误.
为什么设计决定不允许在同一型号上使用Copy
和Drop
?
Drop
特征用于RAII上下文中,通常是当对象被销毁时需要释放/关闭某些资源时.Copy
类型是一种普通类型,只能用memcpy
复制.有了这两种描述,就更清楚地表明它们是排他性的:memcpy
个非平凡的数据毫无意义:如果我们复制数据,并删除其中一个副本,会怎么样?另一个副本的内部资源将不再可靠.
事实上,Copy
甚至不是一个"真正的"特征,因为它没有定义任何功能.这是一个特殊的marker,它对编译器说:"你可以用一个简单的字节拷贝复制我自己".所以不能提供Copy
的自定义实现,因为根本没有实现.但是,可以将类型标记为可复制:
impl Copy for Foo {}
或者更好,用一个派生词:
#[derive(Clone, Copy)]
struct Foo { /* ... */ }
只有当所有字段都实现Copy
时,才会生成此函数.否则,编译器会拒绝编译,因为这是不安全的.
作为示例,我们假设File
struct 实现Copy
.当然,情况就是这样,这个例子是错误的,无法编译:
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();
}