GitHub

设计模式

使用借用类型作为参数

Rust设计模式,惯用做法一:编码时应该总是倾向于使用借用类型,而不是借用所有类型。

例如:

  • 对于String类型来说,应该倾向于使用&str,而不是&String
  • 对于T类型来说,应该倾向于使用&[T]而不是&Vec[T]; 应该倾向于使用&T,而不是&Box<T>

Why

也许我们可以在《Rust设计模式》这本书中找到答案,其中提到:使用借用类型可以避免已经提供一层间接性的所有类型的多层间接,以下代码:

let a: String = "content".to_string();
let b: &String = &a;
let c: &str = a.as_str();

内存分配如下图:

Alt

结合上面的图,我们可以理解:

  • String类型具有一层间接,因为String类型的本质是一个具有三个字段的胖指针(三个字段分别是ptrcaplenptr指向在堆上的具体内容)
  • &String具有两层引用,是因为是String的基础上,加了&,所以b实际指向的是a,而不是堆上的内容
  • &str类型也是一个胖指针,直接指向堆上的内容

所以对比&String&str,显然使用&str的效果更高。从这个层面上说,这条规则本质是想倾向于使用间接层面更少的方式。

我们再考虑下面的例子:

fn print_use_string(word: String) {
println!("{:?}", word);
}
fn print_use_string1(word: &String) {
println!("{:?}", word);
}
fn print_use_str(word: &str) {
println!("{:?}", word);
}
fn main() {
let a = "content".to_string();
print_use_string(a);
// 所有权已经发生转移
let b = "content".to_string();
print_use_string1(&b);
println!("b: {:?}", b);
let c = "content".to_string();
print_use_str(&c);
println!("c: {:?}", c);
print_use_str("content");
}

上面这个例子中,print_use_stringprint_use_str功能一样,所以传引用即可,而传&str比传&String效率更高。

上一篇
所有权机制的66个场景