话不多说,直接上代码
rust
fn main() {
let aa: i32 = 10;
print_i32(aa);
print_i32(aa);
}
fn print_i32(a: i32){
println!("aa = {a}");
}
运行结果
rust
aa = 10
aa = 10
没有什么特别呀
那么,请看下面一段代码
rust
fn main() {
let city_shenzhen = String::from("ShenZhen");
print_city(city_shenzhen);
print_city(city_shenzhen);
}
fn print_city(city: String){
println!("city = {city}");
}
编译报错啦:

报错信息如下:
rust
use of moved value: `city`
value used here after move
main.rs(3, 16): value moved here
main.rs(2, 9): move occurs because `city` has type `String`, which does not implement the `Copy` trait
main.rs(7, 21): consider changing this parameter type in function `print_city` to borrow instead if owning the value isn't necessary
main.rs(3, 20): consider cloning the value if the performance cost is acceptable: `.clone()`
编译报错涉及到所有权问题,city_shenzhen作为参数传递给print_city,所有权被转移到了print_city函数内部,第一次print_city拿到参数,但是第一次调用结束后,city_shenzhen已经被销毁了,所以第二次调用会有问题。rust编译器不给你使用一个已销毁的参数
如果熟悉java和cpp等语言都知道,参数传给函数是有拷贝的动作的。这也是Rust相对于其他语言性能更好的原因,它对于一些复杂的数据,在传参时,只转移所有权,不进行拷贝
慢着,为什么文章开头那段代码,i32作为参数的函数,多次调用没有问题?
因为i32这些比较简单的数据,在拷贝的时候,性能代价一般较小,简单数据基本实现了Copy特性。
实现了Copy特性的数据,在作为参数传递时,传递的是拷贝的副本,没有所有权的转移。参数传递有两种途径,没有实现Copy特性,走所有权转移,实现了Copy特性,走拷贝副本。
如何处理String这种所有权会转移的数据需要多次调用的场景?答案是使用引用
rust
fn main() {
let city_shenzhen = String::from("ShenZhen");
print_city(&city_shenzhen);
print_city(&city_shenzhen);
}
fn print_city(mut city: &String){
println!("city = {city}");
}
运行结果:
rust
city = ShenZhen
city = ShenZhen
不过,有的时候希望将传递进来的String处理一下变为其他字符串,怎么做?看以下代码
rust
fn main() {
let mut city_shenzhen = String::from("ShenZhen");
println!("before print_city called,city_shenzhen = {}",city_shenzhen);
print_city(&mut city_shenzhen);
print_city(&mut city_shenzhen);
println!("after print_city called,city_shenzhen = {}",city_shenzhen);
}
fn print_city(city: &mut String) {
if !city.starts_with("I am ") {
city.insert_str(0, "I am ");
}
println!("{city}");
}
运行结果:
rust
before print_city called,city_shenzhen = ShenZhen
I am ShenZhen
I am ShenZhen
after print_city called,city_shenzhen = I am ShenZhen
有时因为特殊原因只能传递String无法传递引用,但又需要多次调用,如何做呢,String没有Copy特性,但有Clone特性,这个有点类似Copy
rust
fn main() {
let city_shenzhen = String::from("ShenZhen");
print_city(city_shenzhen.clone());
print_city(city_shenzhen.clone());
}
fn print_city(mut city: String){
println!("city = {city}");
}
运行结果:
rust
city = ShenZhen
city = ShenZhen
这个其实就是调用String的clone函数创建了一个拷贝副本传给函数,没有所有权的转移,自然是可以多次调用的