什么时候在Rust通用函数中将输入作为T或&T?

ena*_*naJ 2 generics rust

我的课堂笔记有代码实现HasArea特征并打印区域,类似于Rust Book示例.教授的笔记如下:

trait HasArea<T> {
    fn area(& self) -> T,
}

fn print<T: Display, S: HasArea<T>>(s: &S) {
    println!("", s.area());  // println sth must impl Display trait
}

struct Circle {
    x: T,
    y: T,
    r: T,
}

impl <T: Copy + Mul <Output = T>>
    HasArea<T> for Circle<T>  
{
    fn area(&self) -> T {
        self.r * self.r
    }
}
Run Code Online (Sandbox Code Playgroud)

将其与shape: T作为输入的Rust Book进行比较:

trait HasArea {
    fn area(&self) -> f64;
}

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl HasArea for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

fn print_area<T: HasArea>(shape: T) {
    println!("This shape has an area of {}", shape.area());
}

fn main() {
    let c = Circle {
        x: 0.0f64,
        y: 0.0f64,
        radius: 1.0f64,
    };

    print_area(c);
}
Run Code Online (Sandbox Code Playgroud)

我不确定教授使用什么s: &S,而Rust Book使用shape: T.任何人都可以帮助实现一个泛型函数时相比,当我们传递一个输入的x: &Tx: T

Dog*_*ert 5

任何人都可以帮助实现一个泛型函数时相比,当我们传递一个输入的x: &Tx: T

x: Foo和你接受的时候一样x: &Foo.以一个x: Foo给出了函数的所有权x,以及(除非xCopy)主叫方将无法再次使用它.

在Rust Book示例中,print_area取得所有权circle,因此您不能在行circle之后使用print_area(circle);.例如,以下内容:

fn main() {
    // ...
    print_area(c);
    print_area(c);
}
Run Code Online (Sandbox Code Playgroud)

抛出此错误:

error[E0382]: use of moved value: `c`
  --> <anon>:29:16
   |
28 |     print_area(c);
   |                - value moved here
29 |     print_area(c);
   |                ^ value used here after move
   |
   = note: move occurs because `c` has type `Circle`, which does not implement the `Copy` trait
Run Code Online (Sandbox Code Playgroud)

根据我的经验,大多数时候你会想要: &T(就像你的教授的说明).只有当您需要结构的所有权时才需要使用: T.Rust Book可能: T用于简单.