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
相关产品推荐
相关产品推荐

