2016-07-06 11 views
6

Tôi có một enum trong Rust có một giá trị mất String. Điều này có thể được chứng minh bằng ví dụ đơn giản này:Làm cách nào để triển khai Clone/Copy cho một enum chứa String?

#[derive(Clone, Copy)] 
enum Simple { 
    Error(String), 
    Okay, 
    Foo([u32; 5]), 
} 

fn main() { 
    let x = Simple::Error(String::from("blah")); 
    let y = x.clone(); 
} 

Giá trị enum Foo trên đại diện cho khoảng 10 enums khác tôi sử dụng mà phải mất loại copyable hoặc mảng trong số họ. Trình biên dịch dường như không phàn nàn về họ, chỉ có Error(String) mà nguyên nhân này:

error: the trait `Copy` may not be implemented for this type; variant `Error` does not implement `Copy` [E0205] 
#[derive(Clone, Copy)] 
       ^~~~ 

note: in this expansion of #[derive_Copy] (defined in src\main.rs) 
help: run `rustc --explain E0205` to see a detailed explanation 

Đối với một số lý do String không copyable. Tôi không hiểu. Làm thế nào để thực hiện Clone cho một enum cho chỉ là một loại trong đó có một vấn đề trong khi sử dụng impl mặc định cho phần còn lại?

Trả lời

16

Copy chỉ định các loại để tạo bản sao bitwise tạo một phiên bản hợp lệ mà không làm mất hiệu lực phiên bản gốc. Điều này không đúng với String, bởi vì String chứa con trỏ tới dữ liệu chuỗi trên heap và giả sử nó có quyền sở hữu duy nhất của dữ liệu đó và do đó khi bạn thả một String, nó sẽ phân phối dữ liệu trên heap và nếu bạn đã tạo bản sao bit của String, khi đó cả hai trường hợp sẽ cố gắng phân phối cùng một khối bộ nhớ, là hành vi không xác định. Vì String không triển khai Copy, , enum của bạn không thể triển khai Copy hoặc, bởi vì trình biên dịch thực thi các loại Copy chỉ gồm Copy thành viên dữ liệu.

Clone chỉ cung cấp phương thức chuẩn clone và tùy thuộc vào từng người triển khai để quyết định cách triển khai. String thực hiện Clone, vì vậy, bạn có thể đặt #[derive(Clone)] trên enum của mình.

+0

Tôi nên thêm Tôi không thấy lý do tại sao Chuỗi không thể triển khai đặc điểm Sao chép theo nguyên tắc hoặc thực hành - Đối tượng QString trong QT có thể được sao chép và chia sẻ và duy trì bộ đệm bên trong. Nếu một bản sao làm một cái gì đó có thể thay đổi bộ đệm lần đầu tiên được nhân bản sao cho các bản sao khác vẫn giữ một tham chiếu đến bộ đệm gốc. Trong QT, thực hành tốt hơn để vượt qua bằng cách tham khảo để tránh đếm nguyên tử nhưng sao chép vẫn hiệu quả. – locka

+0

@locka vì * 'Sao chép' chỉ định các loại để tạo bản sao bitwise tạo một phiên bản hợp lệ *. Sao chép các bit của một chuỗi như vậy không thể tăng một truy cập nguyên tử, bởi vì nó sẽ không được sao chép nữa. Bạn có thể chọn những gì đảm bảo bạn cần. Bạn có thể [chia sẻ quyền sở hữu] (http://doc.rust-lang.org/std/rc/struct.Rc.html), [chia sẻ quyền sở hữu trên các chủ đề] (http://doc.rust-lang.org/std /sync/struct.Arc.html), triển khai [clone on write] (http://doc.rust-lang.org/std/borrow/enum.Cow.html), v.v. Nó sẽ không tốt cho một hệ thống ngôn ngữ để đưa ra quyết định đó (và gánh nặng mã của bạn) cho bạn. – Shepmaster

Các vấn đề liên quan