为何无法从含String的结构体引用迭代器收集Vec<&str>?
问题解答:从
Vec<Channel>收集Vec<&str>的疑惑 一、为何必须显式调用as_str()?
你提到的**解引用强制转换(deref coercion)**确实允许&String隐式转为&str,但它只在特定上下文生效,而collect()的类型匹配场景不在其中:
迭代器Item类型与trait约束不匹配
当你写channels.iter().map(|x| &x.name)时,迭代器的Item类型是&String。而collect()要生成Vec<&str>,需要目标类型实现FromIterator<&String>,但标准库仅为Vec<&str>实现了FromIterator<&str>,并没有实现前者。trait匹配是严格类型匹配
Rust的trait系统不会自动为了满足约束而触发隐式类型转换。deref coercion仅发生在直接的类型赋值、函数参数传递、方法调用接收者等场景,比如你把&String传给一个要求&str的函数时,编译器会自动转换。但在collect()的trait约束检查中,编译器不会主动把&String转为&str来匹配FromIterator<&str>,因此必须显式转换。除了
as_str(),你也可以用&*x.name来实现转换(*x.name通过Deref得到str,再取引用就是&str),效果和as_str()完全一致。
二、as_str()和直接取引用的性能对比?
完全等价,没有任何性能差异:
String::as_str()的底层实现就是返回内部的字符串切片,源码大致如下:fn as_str(&self) -> &str { &self[..] }- 而
&*x.name是通过解引用String(利用Deref<Target=str>trait)得到str,再取引用得到&str,本质和as_str()是同一个操作,都是直接获取底层字符数组的不可变引用,没有额外的内存分配或计算开销。
内容的提问来源于stack exchange,提问作者Harjun751
相关产品推荐
相关产品推荐

