在下面的代码中,在calculate_length函数中我们发送的是String而不是&String,但解引用是有效的。我预计会出现错误: 类型
String
无法取消引用
但是代码编译并运行时没有任何错误/警告。
fn main() {
let x = String::from("hello world");
let z = calculate_length(x);
println!("{:}", z);
}
fn calculate_length(s: String) -> usize {
(*s).len()
}
String
实现了Deref
,这意味着您可以在其上使用解引用运算符*
。但是,您部分正确地认为 s
无法取消引用。如果您编写 let x = *s;
,它将无法编译,因为这会复制 String
的目标类型 str
。并且 str
无法复制,因为它由于未调整大小而未实现 Copy
。
但是,虽然
*s
不能是值,但它是一个有效的位置表达式,这意味着您可以对其执行一些操作,例如分配给它,使其成为引用&*s
,或者调用它的方法。
方法非常灵活,可以添加引用和取消引用,以便找到具有指定名称的合适函数。在
(*s).len()
中,该方法添加 &
以便调用 str::len
,这看起来像 str::len(&*s)
展开了。添加的引用使 str
无需被复制。然后取消引用 *s
扩展为 str::len(&*Deref::deref(&s))
。