Rust中为何vec_loop需显式解引用,而vec_map无需?
Rustlings vecs2.rs:为何vec_loop需显式解引用而vec_map不用?
问题代码与错误
编写的代码
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> { for element in v.iter_mut() { // TODO: 将Vec中每个元素乘以2 element = element * 2; // 此处报错! } // 最终v应为[4, 8, 12, 16, 20] v } fn vec_map(v: &Vec<i32>) -> Vec<i32> { v.iter().map(|element| { // TODO: 同样将每个元素乘以2,但不修改原Vec element * 2 // 无报错 }).collect() }
报错信息
error[E0369]: cannot multiply `&mut i32` by `{integer}` --> exercises/vecs/vecs2.rs:16:28 | 16 | element = element * 2; // error here!!! | ------- ^ - {integer} | | | &mut i32 | help: `*` can be used on `i32` if you dereference the left-hand side | 16 | element = *element * 2; // error here!!! | +
核心疑问
为什么vec_loop里必须显式写*element才能运算,而vec_map里直接用element *2就可以?
原因解析
1. vec_map中的隐式解引用:运算符重载的语法糖
v.iter()返回只读迭代器Iter<i32>,迭代出的element是&i32类型(对原元素的不可变引用)。
Rust标准库为**不可变引用&T**实现了Mul(乘法)运算符重载——当T本身支持乘法时,&T可以直接和对应类型做运算,编译器会自动完成解引用操作,相当于把element *2转换成(*element) *2。这是Rust为简化代码提供的语法糖,因此不需要手动写*。
2. vec_loop中的显式解引用:两个必须的理由
v.iter_mut()返回可变迭代器IterMut<i32>,迭代出的element是&mut i32类型(对原元素的可变引用):
- 运算层面:标准库没有为**可变引用
&mut i32**实现和整数的乘法重载,直接写element *2会报错,必须显式解引用成i32类型才能和整数相乘。 - 赋值层面:你要修改的是引用指向的内存中的值,而非引用变量本身。
element是&mut i32类型的变量,若写element = ...,是试图把i32值赋值给引用变量,类型完全不匹配。正确做法是通过*element访问目标内存,再给它赋值:*element = *element *2。
修正后的vec_loop代码
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> { for element in v.iter_mut() { *element = *element * 2; } v }
总结
vec_map里的隐式解引用是运算符重载带来的语法糖,仅针对不可变引用的运算场景;vec_loop里需要显式解引用,一是因为可变引用没有对应的乘法重载,二是因为要修改引用指向的内存值,必须通过解引用来访问目标地址。
内容的提问来源于stack exchange,提问作者Archsx
相关产品推荐
相关产品推荐

