rust 当参数作为引用传入时,为什么泛型函数需要Copy trait?

mnowg1ta  于 2023-05-07  发布在  其他
关注(0)|答案(1)|浏览(120)

我的主要编程语言是Java,我刚刚开始接触低级语言,如C/C和Rust。因为Java有一个垃圾收集器,所以我从来不用担心内存管理。进入C/C和Rust让我意识到我对指针、引用等知之甚少。
如果我有一个简单的泛型函数,例如:

fn get_average <T> (x: &T, y: &T) -> T
    where T: Add<Output = T> + Div<Output = T> + From<u8>
{
    (*x + *y) / T::from(2)
}

编译器将输出以下内容:

error[E0507]: cannot move out of `*x` which is behind a shared reference
  --> src\main.rs:12:6
   |
12 |     (*x + *y) / T::from(2)
   |     -^^------
   |     ||
   |     |move occurs because `*x` has type `T`, which does not implement the `Copy` trait
   |     `*x` moved due to usage in operator
   |
note: calling this operator moves the left-hand side

error[E0507]: cannot move out of `*y` which is behind a shared reference
  --> src\main.rs:12:11
   |
12 |     (*x + *y) / T::from(2)
   |           ^^ move occurs because `*y` has type `T`, which does not implement the `Copy` trait

当我传入x和y作为引用时,为什么T需要'Copy' trait?任何帮助都非常感谢!

qoefvg9y

qoefvg9y1#

当你通过引用传递一个变量时(在Rust中),你是在借用它,这意味着你不拥有数据,你不能把它移出引用。在代码中,您试图通过使用 * 运算符取消引用来将值移出引用。
一个解决方案是你可以改变函数签名来接受Copy trait。然后,您可以在函数内部修改x和y的值,因为 * 运算符可用。
Playground

use std::ops::{Add, Div};

fn get_average<T>(x: &T, y: &T) -> T
    where T: Add<Output = T> + Div<Output = T> + From<u8> + Copy
{
    (*x + *y) / T::from(2)
}

fn main() {
    let x = 420;
    let y = 69;
    let avg = get_average(&x, &y);
    println!("The average of {} and {} is {}", x, y, avg);
}

这里我们使用Copy trait来表示一个类型可以通过简单地复制它在内存中的位来复制,而不需要任何深复制。

相关问题