代码出自 rustlings:
第一种:
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
// 文档中说 iter 返回 (&'a K, &'a V),也就是 map 的 K 和 V 的引用组成的 tuple 。
// 然后这个 tuple 被 deconstruct 了,且 V move 给了 v ,顺带地 map 也被 move 了?
map.iter().filter(|(_, &v)| v == value).count()
}
第二种:
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
// 无法理解为什么要 2 次 deref
map.iter().filter(|(_, v)| **v == value).count()
}
第三种:
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
// 请问这里 value 也是 move 给了 v 吗?那和第一种的区别是?
map.iter().filter(|&(_, &v)| v == value).count()
}
第四种:
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
// 首先 &(_, v) borrow map 的 (&'a K, &'a V),然后这个 tuple 被 deconstruct ,v 是
// &'a V ,所以 deref v 拿到值,从而和 value 参数的值进行比较
map.iter().filter(|&(_, v)| *v == value).count()
}
理解上可能有误,还请大佬们指正,谢谢!
1
palfortime 2022-03-05 18:02:26 +08:00 via Android
map 只是一个&,不是&mut ,不可能发生 move ,Progress 应该实现了 Copy 吧。
|
2
chuanqirenwu OP @palfortime 是的,那这么来看所有的操作都是引用了,就是不知道各种写法间细微的区别是什么样的了。
|
3
gfreezy 2022-03-05 20:26:25 +08:00 via iPhone
实际使用都是引用,没啥区别。pattern match 的时候编译器会自动加&
|
4
chuanqirenwu OP 经过一番调查我可能大致理解了,先来看不带任何 & 的情况,
即:`map.iter().filter(|(_, v)| **v == value).count()`。首先 filter 会以引用的形式去迭代 map.iter() 返回的类型(&K, &V ),因此 filter 迭代的类型是 &(&K, &V),此类型被 (_, v) match ,因此 v 具有类型 &&V ,如果我们调用 V 的方法,由于 rust 的 deref coercions ,这是没有问题的,但如果和不一致的类型比较,就会报错,想取到 v 的值,需要 2 次 deref ,即 **v 。 再来看:`map.iter().filter(|&(_, v)| *v == value).count()`,根据前面的分析,&(_, v) pattern 帮忙脱掉了一层 &,因此 v 的类型变为 &V 。 再来看:`map.iter().filter(|(_, &v)| v == value).count()`,第二个位置的参数匹配的值的类型为 &&V ,匹配模式为 &v ,由于 rust 的 deref coercions ,变为 &V 匹配 &v ,V move or copy to v 。 最后 `map.iter().filter(|&(_, v)| *v == value).count()`,第二个参数匹配的值的类型为 &V ,因此 v 的值为 &V ,做一次 deref 取得 V 的值。 如此,所有情况都解释的通了,而且分析发现最好的写法应该是:`map.iter().filter(|&(k, v)| *v == value).count()`,这样 k 的类型是 &K ,v 是&V ,不存在 move 或者 copy 的情况。 |
5
gydi 2022-03-06 00:28:06 +08:00 1
`|(_, v)| *v == &value`
`|&(_, v)| v == &value` `|(_, v)| v == &&value` 这样也不用 copy |
6
macrorules 2022-04-04 17:49:54 +08:00 1
新注册的号不能连续回复,所以发个粘贴板:dpaste.org/Aa6k9oD
|
7
chuanqirenwu OP @macrorules 非常感谢,不过这个帖子时 rust 的,你这个粘贴板的内容应该对应这个帖子:/t/844896
我大概理解,从指针的地址来看,确实 m2 已超过栈顶范围,但在我的电脑环境下,取 m2 指向的地址里的值,仍然可以取到,所以得到了帖子中说的结果。但如几位大佬所说,这是一个 ub 。 |