You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust模式匹配中ref关键字与&符号的区别

Rust模式匹配中&与ref的差异辨析

两者的核心区别是作用位置完全不同:&写在match的匹配目标(也就是match后面跟的表达式)位置,作用是给待匹配的值取引用,避免整体所有权被match拿走;ref写在match分支的模式里,作用是解构时把对应变量绑定为引用,不拿走内部值的所有权。

你写的三段match逻辑运行结果一致,本质是因为三种写法最终都拿到了指向内部Point的不可变引用,没有触发所有权转移,我们逐段拆解:


第一段match:匹配目标加&

match &y {
    Some(p) => println!("Co-ordinates are {},{} ", p.x, p.y),
    _ => println!("no match"),
}
  • 这里match拿到的是&Option<Point>类型,从一开始就没有获取y的所有权。
  • 按照Rust的匹配人体工学规则,解构引用类型的Option时,分支里的p会自动被推导为&Point类型,不需要额外加关键字。
  • 这是目前Rust代码里最常用的写法,简洁清晰。

第二段match:模式里加ref

match y {
    Some(ref p) => println!("Co-ordinates are {},{} ", p.x, p.y),
    _ => println!("no match"),
}
  • 这里match直接拿y本身(Option<Point>类型)做匹配,如果不加ref写Some(p),p会直接拿到Point的所有权,整个y的所有权会被分支消耗,后续代码无法再使用y。
  • 模式里写ref p就是显式告诉编译器:不要把内部Point的所有权移给p,只给我绑定一个指向Point的不可变引用(p: &Point)。这种写法下,虽然match匹配的是y本身,但因为没有拿走内部值的所有权,y在match结束后依然有效。
  • 本质上ref是模式侧的关键字,和表达式侧造引用的&是对称的反向操作:表达式里&val生成一个引用,模式里ref p匹配并接住一个引用。

第三段match:同时加&和ref

match &y {
    Some(ref p) => println!("Co-ordinates are {},{} ", p.x, p.y),
    _ => println!("no match"),
}
  • 这是合法但冗余的写法:匹配目标已经是&Option<Point>,按照匹配规则本来就会把p推导为&Point,再加ref本来应该得到&&Point,但Rust的匹配人体工会自动抹平多余的引用层级,最终p的类型还是&Point,所以运行效果和前两段完全一致,日常写代码不需要这么写。

使用建议

  • 只要你不需要在match里修改值、也不需要消费掉原变量,优先用match &xxx的写法,解构出来的绑定默认就是引用,不需要额外加ref,代码更干净。
  • 如果你需要匹配值本身(比如要修改内部值、或者要部分移动内部的某个字段),再在对应字段的绑定前加ref(可变场景用ref mut)即可。
  • 三段代码都能正常访问p.x/p.y的原因是Rust的自动解引用规则:不管绑定是几层引用,访问字段时都会自动解引用到目标类型,不会影响字段读写。

内容的提问来源于stack exchange,提问作者Michael Pacheco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 21:30:56