当进行加法运算时,i32类型的不可变引用和可变引用有什么区别?

3

I have

fn plus_one(x: &i32) -> i32 {
    x + 1
}

fn plus_one_star(x: &i32) -> i32 {
    *x + 1
}

fn plus_one_mut(x: &mut i32) -> i32 {
    x + 1
}

fn plus_one_mut_star(x: &mut i32) -> i32 {
    *x + 1
}

fn main() {
    let a: i32 = 5;
    let mut b: i32 = 5;

    println!("{:?}", plus_one(&a));
    println!("{:?}", plus_one_star(&a));
    println!("{:?}", plus_one_mut(&mut b));
    println!("{:?}", plus_one_mut_star(&mut b));
    // I expect all to print '6' as I never actually mutate b
}

第三个函数plus_one_mut编译失败,错误提示为:error[E0369]: binary operation `+` cannot be applied to type '&mut i32'
为什么这个带有可变引用的函数无法编译?
1个回答

5
正如错误信息所说:
二进制操作 + 不能应用于类型'&mut i32'
这是因为它没有被实现。查看 i32 的文档, 您将看到这些Add的实现:
- impl Add<i32> for i32 - impl<'a> Add<i32> for &'a i32 - impl<'a> Add<&'a i32> for i32 - impl<'a, 'b> Add<&'a i32> for &'b i32 您需要解引用&mut i32以获取i32,后者确实有一个Add实现。
为什么它没有这个实现呢?我不确定。也许你可以提交一个PR到Rust来添加它...就我个人而言,我不能回忆起曾经需要过它。通常,如果你有一个&mut T,那是因为你想要更新它,所以你会有类似于*foo += 1的东西。

2
奇怪的是,x.add(1) 在所有情况下都起作用......在这种情况下,可能是强制转换发挥了作用? - Paolo Falabella
@PaoloFalabella 我不确定“coercion”是否为正确术语;但是,我认为自动解引用正在发挥作用。[链接已省略] - Shepmaster
所以在这种情况下,&T 的行为就像 T 一样。但总的来说,在使用不可变引用之前,我是否应该对它们进行解引用?或者实现大多数 T 方法的 &T 是非常普遍的? - turbulencetoo
@turbulencetoo 我不确定我是否理解你的意思。如果你有一个值,你可以调用该类型的方法,这些方法接受&self或者没有额外修饰的self。方法实现是采用self还是&self取决于函数需要做什么。我敢打赌大多数方法都采用&self,因为它们不需要&mut self或者self所提供的功能。我发现很少有必要显式添加*,通常我会等到编译器提示我添加它。 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接