代码之家  ›  专栏  ›  技术社区  ›  msrd0 Gordon Linoff

AddAssign与“+=”运算符之间的关系

  •  1
  • msrd0 Gordon Linoff  · 技术社区  · 4 年前

    到目前为止,我的理解是,在Rust中,操作符基本上是trait方法调用的语法糖。尤其是,我认为 a += b 相当于写作 a.add_assign(b) . 今天我非常惊讶地听到rustc(1.44.1)的以下消息:

    error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut u8`
     --> src/main.rs:2:5
      |
    2 |     a += b;
      |     -^^^^^
      |     |
      |     cannot use `+=` on type `&mut u8`
      |
    help: `+=` can be used on 'u8', you can dereference `a`
      |
    2 |     *a += b;
      |     ^^
    

    导致错误消息的代码是( Playground

    fn test_add_assign(a: &mut u8, b: u8) {
        a += b;
    }
    
    fn main() {
        let mut test = 1;
        test_add_assign(&mut test, 1);
        assert_eq!(test, 2);
    }
    

    现在,编译器是正确的,正在编写 *a += b 也可以正确地将新变量指定给。然而,令我惊讶的是 a、 添加分配(b) 工作非常好,无需取消引用 a ( Playground

    fn test_add_assign(a: &mut u8, b: u8) {
        a.add_assign(b);
    }
    

    鉴于 AddAssign

    加法赋值运算符 +=

    我在想:你们之间是什么关系 添加分配 以及 += 操作符,如果它不是调用trait方法的基本语法糖?

    0 回复  |  直到 4 年前
        1
  •  2
  •   Sven Marnach    4 年前

    我以为 a += b a.add_assign(b) .

    不完全是, 实际上被翻译成 ::std::ops::AddAssign::add_assign(&mut a, b) &mut &mut u8

    如果你仔细想想,这是有道理的。整数变量的标准赋值 i 写为 i = 3; . 如果你想让它成为一个函数调用,你需要传递一个可变的引用

    注意方法调用语法 a、 添加分配(b) 在这种情况下碰巧有用,因为 method calls treat the receiver in a special way . 编译器通过隐式地借用和取消引用接收者来寻找匹配方法,直到找到匹配为止。对带有类型参数的traits的方法调用也很特殊,因为搜索甚至可能继续为 其他 该方法的参数(我认为目前在Rust参考中没有记录)。

        2
  •  1
  •   rodrigo    4 年前

    我认为让你困惑的问题是 在方法函数调用中。详见 this other question

    let x = 42;
    let _ = x.to_string(); //ok
    let _ = (&x).to_string(); //ok
    let r = &x;
    let _ = r.to_string(); //ok
    let _ = (*r).to_string(); //ok
    

    但当使用自动 不适用。所以:

    let mut x = 42;
    x += 1; //ok;
    x.add_assign(1); //ok
    let r: &mut i32 = &mut x;
    *r += 1; //ok
    r += 1; //error: &mut i32 does not implement AddAssign
    r.add_assign(1); //ok: r is auto-dereffed
    

    注意左边的表达式 += 必须是要修改的值(右值),而不是对该值的引用。那么,实际上当你写作的时候 a += b AddAssign::add_assign(&mut a, b)