首页 文章

为什么Rust不允许复制和删除一种类型的特征?

提问于
浏览
11

来自the book

如果类型或其任何部分已实现Drop特征,Rust将不允许我们使用Copy trait注释类型 . 如果类型需要在值超出范围时发生特殊情况并且我们将复制注释添加到该类型,那么我们将得到编译时错误 .

为什么设计决定不允许 CopyDrop 在同一类型上?

2 回答

  • 4
    • Drop trait用于RAII上下文,通常是在销毁对象时需要释放/关闭某些资源时 .

    • 另一方面, Copy 类型是一种普通类型,只能用 memcpy 复制 .

    有了这两个描述,就更清楚它们是独占的:对于非常重要的数据没有意义:如果我们复制数据,我们丢弃其中一个副本会怎么样?另一个副本的内部资源将不再可靠 .

    事实上, Copy 甚至没有"real"特性,因为它没有定义任何功能 . 这是一个特殊的 marker 对编译器说:"you can duplicate myself with a simple bytes 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();
    }
    
  • 15

    引用documentation .

    [...] [A]类型实现Drop不能复制,因为它除了自己的size_of :: <T>字节之外还管理一些资源 .

相关问题