Rust 这 4 种写法都通过编译了,但不知道我这样理解是对的吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chuanqirenwu
V2EX    Rust

Rust 这 4 种写法都通过编译了,但不知道我这样理解是对的吗?

  •  
  •   chuanqirenwu 2022-03-05 16:29:42 +08:00 3727 次点击
    这是一个创建于 1318 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码出自 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() } 

    理解上可能有误,还请大佬们指正,谢谢!

    7 条回复    2022-04-04 18:10:34 +08:00
    palfortime
        1
    palfortime  
       2022-03-05 18:02:26 +08:00 via Android
    map 只是一个&,不是&mut ,不可能发生 move ,Progress 应该实现了 Copy 吧。
    chuanqirenwu
        2
    chuanqirenwu  
    OP
       2022-03-05 18:22:04 +08:00
    @palfortime 是的,那这么来看所有的操作都是引用了,就是不知道各种写法间细微的区别是什么样的了。
    gfreezy
        3
    gfreezy  
       2022-03-05 20:26:25 +08:00 via iPhone
    实际使用都是引用,没啥区别。pattern match 的时候编译器会自动加&
    chuanqirenwu
        4
    chuanqirenwu  
    OP
       2022-03-05 23:51:54 +08:00
    经过一番调查我可能大致理解了,先来看不带任何 & 的情况,
    即:`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 的情况。
    gydi
        5
    gydi  
       2022-03-06 00:28:06 +08:00   1
    `|(_, v)| *v == &value`
    `|&(_, v)| v == &value`
    `|(_, v)| v == &&value`

    这样也不用 copy
    macrorules
        6
    macrorules  
       2022-04-04 17:49:54 +08:00   1
    新注册的号不能连续回复,所以发个粘贴板:dpaste.org/Aa6k9oD
    chuanqirenwu
        7
    chuanqirenwu  
    OP
       2022-04-04 18:10:34 +08:00
    @macrorules 非常感谢,不过这个帖子时 rust 的,你这个粘贴板的内容应该对应这个帖子:/t/844896

    我大概理解,从指针的地址来看,确实 m2 已超过栈顶范围,但在我的电脑环境下,取 m2 指向的地址里的值,仍然可以取到,所以得到了帖子中说的结果。但如几位大佬所说,这是一个 ub 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3208 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 12:07 PVG 20:07 LAX 05:07 JFK 08:07
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86