Rust中“重借用(reborrow)”与“解引用(deref)”的区别是什么?
关于Clippy警告中两种建议的区别
先明确场景:假设s的类型是&String(对String的不可变引用)。
1. 移除&*:重借用(保持原引用类型)
当你写&*s时,*s会把&String解引用成String,紧接着&又给这个String重新取了一个&String类型的引用。但这个操作完全多余——s本身就是&String,直接用s就等价于&*s,本质是复用原有的引用,类型依然是&String。
比如你有函数fn take_string_ref(s: &String) { ... },调用take_string_ref(&*s)和take_string_ref(s)效果完全一致,移除&*既简洁又不改变逻辑。
2. 使用&**:解引用到底层的str(改变引用类型)
String实现了Deref<Target=str>,意味着String可以被自动解引用成str。&**s的拆解逻辑是:
- 第一层
*s:把&String解引用成String - 第二层
*:把String解引用成str - 最后
&:给str取引用,得到&str
这时候你得到的是&str类型的引用,而非原来的&String。这种写法适合你明确需要&str类型的场景,比如函数fn take_str(s: &str) { ... },虽然Rust会自动做Deref强制转换,但显式写&**s可以清晰表达你想要的是字符串切片而非String的引用。
举个直观的代码示例:
let s: &String = &"hello".to_string(); // 移除&*:类型仍为&String let ref1: &String = &*s; let ref1_same: &String = s; // 使用&**:类型变为&str let ref2: &str = &**s;
简单总结
- 若只是想传递原有的
&String引用,直接去掉&*即可,完全没必要多此一举; - 若需要的是
&str类型,就用&**s来明确解引用到底层字符串切片。
内容的提问来源于stack exchange,提问作者suchapalaver
相关产品推荐
相关产品推荐

