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

为何Rust示例中`ref`会导致字段被解引用?

为什么在匹配可变引用时,加ref反而能让代码编译?

先拆解问题里的核心逻辑:你的代码里匹配的是可变引用&mut Thing,模式匹配的行为在面对引用类型时,和匹配值类型的规则不一样,这是关键。

1. 不加ref时的问题

当你写if let Thing::A { value } = thing_mut_ref时,thing_mut_ref是&mut Thing类型。Rust的模式匹配在处理可变引用时,会自动为字段创建可变引用绑定——也就是说value的类型是&mut f32。

而标准库中并没有为&mut f32和f32实现乘法(Mul trait),所以直接写value * 2.0会报错:编译器不知道怎么把可变引用和浮点数相乘。这时候你如果改成*value * 2.0,手动解引用可变引用为f32,代码也能正常编译。

2. 加ref后的变化

当你在模式里加上ref,写成if let Thing::A { ref value } = thing_mut_ref时,ref关键字改变了绑定的类型:原本会绑定&mut f32,现在ref告诉Rust:“我要的是这个字段的共享引用”,也就是value的类型变成了&f32。

而标准库为&f32和f32实现了Mul trait,编译器会自动解引用&f32为f32来执行乘法运算,所以value * 2.0能正常编译。

3. 关于ref的“反向”直觉

你觉得ref是“不希望按值捕获”,这个理解没错——但那是针对匹配值类型的场景。比如当你匹配Thing类型(不是引用)时,Thing::A { value }会按值捕获f32,而Thing::A { ref value }会捕获&f32。

但当你匹配的是引用类型(比如&mut Thing)时,默认的绑定已经是引用了,这时候ref的作用是把可变引用转换成共享引用,而不是从值转成引用——这就是为什么看起来和直觉相反的原因。

替代写法

除了加ref,你也可以手动解引用可变引用,或者先解引用整个thing_mut_ref再匹配:

// 手动解引用可变引用
if let Thing::A { value } = thing_mut_ref {
    *thing_mut_ref = Thing::B { value: *value * 2.0 };
}

// 先解引用整个可变引用再匹配
if let Thing::A { value } = &mut *thing_mut_ref {
    *thing_mut_ref = Thing::B { value: *value * 2.0 };
}

内容的提问来源于stack exchange,提问作者Alex Hastings

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:35:22