String是一种不实现Copy复制trait的类型(String默认是值传递,不是引用传递,也不是值复制):
让我们用它创建一个Stringthen 调用do_something:
fn main() { let name = String::from("Rust"); do_something(name); }
fn do_something(name: String) { println!("Hello, {}!", name); }
|
在第 4 行添加一个println!语句……
fn main() { let name = String::from("Rust"); do_something(name); println!("{}", name); }
fn do_something(name: String) { println!("Hello, {}!", name); }
|
编译器:
error[E0382]: borrow of moved value: `name` --> src/main.rs:4:20
|
这是不合法的!
因为我们试图使用(借用,在println的情况下!)已经在第3行被移入do_something的值名。(String默认是值传递,不是引用传递)
你不能使用一个已经被移动过的值。
在 println!之前的name 已经被移到 do_something 中,并在函数结束时超出了作用域。
我们可以做的是将name克隆为name_clone,(原型模式)
这样我们在第5行使用name,在第6行使用name_clone。请注意,克隆是有代价的。
fn main() { let name = String::from("Rust"); let name_clone = name.clone();
do_something(name); println!("{}", name_clone); }
fn do_something(name: String) { println!("Name: {}!", name); }
|
或者我们可以在第3行通过引用将名字传给do_something,并且仍然能够在第4行将它用于println!
fn main() { let name = String::from("Rust"); do_something(&name); println!("{}", name); }
fn do_something(name: &str) { println!("Hello, {}!", name); }
|
或者,如果你的程序允许,我们可以简单地把代码行相互调换一下顺序。
在这里,我们先借用name,然后再把它移到do_something中。这个程序可以编译,因为在do_something行之后,主作用域中没有其他人会使用name。
fn main() { let name = String::from("Rust"); println!("{}", name); do_something(name); }
fn do_something(name: String) { println!("Hello, {}!", name); }
|