大白话rust系列09 函数调用两次有什么错?

话不多说,直接上代码

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函数创建了一个拷贝副本传给函数,没有所有权的转移,自然是可以多次调用的

相关推荐
投图匠11 分钟前
十种不同风格的 CTP接口 框架
开发语言·python
2601_967980112 小时前
深入理解词向量算法及其在Python中的实践
python·word2vec·glove·fasttext·词向量
129Lab2 小时前
电池循环测试数据自动化分析:用Python+AI工具构建一键式寿命评估流水线
python·数据分析·电池测试·数据自动化·寿命评估
treasure1402 小时前
【复古】浅尝Django前后端不分离
前端·css·python·django·bootstrap·html·web
Dmz丶3 小时前
前端转 AI 100 天 Day 44:前端集成实战——用 React 给 Agent 做个正式界面
python
jay神3 小时前
基于 YOLOv8 的手势识别系统(Web 版)
前端·人工智能·python·深度学习·yolo·计算机视觉·计算机毕业设计
DeepVisionary3 小时前
阿里云上线旗舰多模态新模型,不公布跑分且限时14天退役
python·自动化
东莞市云毅网络有限公司3 小时前
FAQ 覆盖度打分:TF-IDF 与向量嵌入双路召回的 Python 实现
python·数据清洗·rag·企业知识库·文档解析
爱笑的k114 小时前
nano-vllm 源码剖析:千行 Python 手写离线推理引擎的调度、显存与并行时序
开发语言·python·vllm
用户8356290780514 小时前
使用 Python 控制 Excel 工作表的分页位置
后端·python