作者yam276 (史莱哲林的优等生)
看板Marginalman
标题Re: [闲聊] Rust: 从入门到入门
时间Thu Mar 27 11:59:43 2025
: https://space.bilibili.com/361469957/lists/3902595
: 从入门到入门
1. Copy接口
fn copy_vs_move() {
let v: Vec<i32> = vec![0, 1, 2];
let n_ref: &i32 = &v[0];
let n: i32 = *n_ref;
let v: Vec<String> = vec![String::from("012")];
let s_ref: &String = &v[0];
let s: String = *s_ref;
}
i32 是基础类型,有 copy 接口,而 String 则没有
因此在 i32 进行 let n = *n_ref 的时候发生的是复制非转移所有权
而 String 进行 let s = *s_ref 的时候因为没有实现复制的接口,
因此会尝试获得所有权(他是 String 而非 &String )造成错误
因为基础型态有实现 copy 接口,所以可以自动解引用
但 String 本身是 Stack 指标储存资料在 Heap 的关系,
所以这边要让 let s = &v[0].clone() 或各种非借用方式来解决
2. 成员变数的所有权
fn tuple_fields() {
let mut name: (String, String) = (
String::from("Ferris"),
String::from("Rustacean")
);
let first: &String = &name.0;
name.1.push_str(", Esq.");
println!("{first} {}", name.1);
}
当使用 let first = &name.0 借用的时候,
name 本身与 name.0 成员失去可变性,
但 name.1 仍然可以借用也能可变借用
因为在 Rust 2018 版本以後,成员变数被当成独立个体,
而更之前的 Rust 版本这样则会编译错误,因为成员变数被当成整体
3. 承以上 code
fn tuple_fields() {
let mut name: (String, String) = (
String::from("Ferris"),
String::from("Rustacean")
);
let first: &String = get_first(&name);
name.1.push_str(", Esq.");
println!("{first} {}", name.1);
}
fn get_first(name: &(String, String)) -> &String {
&name.0
}
如果是这样,在 let first: &String = get_first(&name); 这行会编译错误,
因为 Rust 不管 Function 内的所有权实作,
因此编译器会判断 get_first(&name); 把整个 name 借走,
此时 name.1 即使在 function 内没被使用也被视为不可变
不过这只是现在版本的判断,有机会跟 2. 提到的一样,
新版本 Rust 如果让编译器变得更聪明了,
就有机会让它判断 function 内部是否有借用来让这段 code 通过,
但至於何时会这样更新,恐怕只有当事人自己知道了……
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 60.248.143.172 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Marginalman/M.1743047985.A.6AF.html
※ 编辑: yam276 (60.248.143.172 台湾), 03/27/2025 12:01:23
1F:推 oin1104: 大师 03/27 12:08