Rust踩雷笔记(1)——切片传参和解引用赋值

最近学习rust,网上资料还是很有限,做题遇到的问题,有时需要自己试验。把自己做题过程遇到的问题,和试验的结论,做一些简单记录。

阅读下列文字和代码

用切片(的引用)做参数要非常小心,切片中的某个元素直接用=赋值,用的是copy方式而不是所有权转移(实践证明)。
如果要用切片中的值赋值,那么可以对切片元素clone(需要元素类型实现Clone trait),
或者限制切片元素类型为实现了copy trait。String没有实现Copytrait,实现了Clone trait
let l: String = *y;(y是&String),这种解引用再用=赋值,走的也是copy方式,
就会报错(String没实现copy trait)
给类型上加#[derive(Copy)]可以添加Copy特征,Copy特征有自己默认实现的代码,
这个类型就可以调用它们,也可以自己重写方法

fn main() {
    let mut x = String::from("hello");
    let y = &x;
    let z = y;
    println!("{}", *y);
    // let l: String = *y;     // 会报错。通过报错信息可知,解引用再用=赋值,是copy操作
    // 直接将String本身用=赋值,是转移所有权;
    // 将String本身的引用,解引用后用=赋值,是copy操作,
    // String没有实现copy特性,所以会报错(上一行)
    let l = x;
}

fn largest2(s: &[String]) -> String {
    // 下面错误,原因是会发生所有权转移,但是s是一个切片(的引用),
    // 切片:[String, String, ... , String],
    // 如果其中某个元素发生了所有权转移,是不被允许的,所以这里只能通过拷贝
    // 但是String没有实现copy trait,所以会报错。正确做法是用clone()
    // let mut res: String = s[0];
    let mut res: String = s[0].clone();
    res
}

/*
重大发现,这个泛型如果不限制它实现copy特征,那么发生传值的时候,
比如我写let x = list[0],注意list是这个切片首地址,list[0]就是切片中首元素,
它是T类型的,这种赋值方式会copy一份给x绑定,如果T没实现copy trait怎么办?
所以要限定T的范围,这里限定T为实现了Copy特征的类型
*/
fn largest<T: std::cmp::PartialOrd + Copy>(list: &[T]) -> T {
    let mut res = &list[0];
    for i in list.iter() {
        if *i > *res {
            res = i;
        }
    }
    *res    // res是T类型的引用,这种返回是用&T
}

// 如果要用clone(),得确保类型实现了Clone
fn largest1<T: std::cmp::PartialOrd + Clone>(list: &[T]) -> T {
    let mut res = list[0].clone();
    for i in list.clone() {
        if *i > res {
            res = i.clone();
        }
    }
    res
}
结构体赋值的例子

这个是从rust圣经上摘录的

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

我们创建了一个user1,代码略,然后用user1更新user2:

  let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };

这里除了email是新创建,其他都是和user1一样。其中username字段进行了所有权转移,原因:

实现了 Copy 特征的类型无需所有权转移,可以直接在赋值时进行 数据拷贝,其中 bool 和 u64 类型就实现了 Copy 特征(来源rust圣经)

由于user1中username的所有权转移给了user2,user1之后就不能使用了。但是通过user1.active、user1.email、user1.sign_in_count可以使用user1中没有失效的属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值