带有字符串字段的结构struct: 如果一个类型的所有组件都实现了Copy,那么它就可以实现Copy(copy类似语言自身的#原型模式概念);
在下面这些列表中,我们关注的是Movie结构,它由一个没有实现Copy的String字段组成(原因见这里),因此,Movie不能实现Copy。
#[derive(Debug)] struct Movie { title: String, } fn main() { let movie = Movie { title: String::from("Rust") }; do_something(movie); } fn do_something(movie: Movie) { println!("Movie: {:?}!", movie); } |
输出:
Movie: Movie { title: "Rust" }! |
但在加入println!后:
#[derive(Debug)] struct Movie { title: String, } fn main() { let movie = Movie { title: String::from("Rust") }; do_something(movie); println!("Movie: {:?}", movie); } fn do_something(movie: Movie) { println!("Movie: {:?}!", movie); } |
error[E0382]: borrow of moved value: |
我们可以借用Movie而不是移动它。(Movie中有String字段,String不是值复制,也就是值无法移动的)
#[derive(Debug)] struct Movie { title: String, } fn main() { let movie = Movie { title: String::from("Rust") }; do_something(&movie); println!("Movie: {:?}", movie); } fn do_something(movie: &Movie) { println!("Movie: {:?}!", movie); } |
Movie: Movie { title: "Rust" }! Movie: Movie { title: "Rust" } |
或者我们可以为do_something克隆movie。这需要Movie实现Clone。
#[derive(Debug, Clone)] struct Movie { title: String, } fn main() { let movie = Movie { title: String::from("Rust") }; do_something(movie.clone()); println!("Movie: {:?}", movie); } fn do_something(movie: Movie) { println!("Movie: {:?}!", movie); } |
或者,如果你的程序允许的话,我们可以在不克隆的情况下把两个代码行调换一下顺序。在这里,把movie借给println!,然后把movie移到do_something。
#[derive(Debug)] struct Movie { title: String, } fn main() { let movie = Movie { title: String::from("Rust") }; println!("Movie: {:?}", movie); do_something(movie); } fn do_something(movie: Movie) { println!("Movie: {:?}!", movie); } |
Struct 包含u8 字段 如前所述,如果一个类型的所有组件都实现了Copy,它就可以实现Copy。 在下面列表中,我们关注的是由一个u8字段组成的Book结构,它实现了Copy特性。因此,Movie应该可以实现Copy的。
#[derive(Debug)] struct Book { id: u8, } fn main() { let book = Book { id: 1 }; do_something(book); } fn do_something(book: Book) { println!("Book: {:?}!", book); } |
直到我们在do_something下面添加一个println!语句。发生了什么?
因为book没有实现Copy特性(或者还没有实现),Rust将book移动到do_something中。但是......因为book被移动了,println! 不能再使用这个值。
#[derive(Debug)] struct Book { id: u8, } fn main() { let book = Book { id: 1 }; do_something(book); println!("Book: {:?}", book); } fn do_something(book: Book) { println!("Book: {:?}!", book); } |
报错:
error[E0382]: borrow of moved value: |
一种方法是通过派生Copy为Book实现Copy特性:
#[derive(Debug, Copy)] struct Book { id: u8, } fn main() { let book = Book { id: 1 }; do_something(book); println!("Book: {:?}", book); } fn do_something(book: Book) { println!("Book: {:?}!", book); } |
还是报错:
error[E0277]: the trait bound |
但是......我们仍然得到一个错误--triay绑定的Book。克隆没有得到满足。
如果我们去看文档,它说所有属于Copy的东西都必须同时实现Clone,因为Clone是一个超级属性。
因此,让我们在现有的Copy特质之上为Book实现Clone特质。
#[derive(Debug, Copy, Clone)] struct Book { id: u8, } fn main() { let book = Book { id: 1 }; do_something(book); println!("Book: {:?}", book); } fn do_something(book: Book) { println!("Book: {:?}!", book); } |
正常输出:
Book: Book { id: 1 }! Book: Book { id: 1 } |
我们也可以重新设计我们的程序,让 do_something 借用Book:
#[derive(Debug)] struct Book { id: u8, } fn main() { let book = Book { id: 1 }; do_something(&book); println!("Book: {:?}", book); } fn do_something(book: &Book) { println!("Book: {:?}!", book); } |