What do I have to do to solve a "use of moved value" error?

I'm trying to compute the 10,001st prime in Rust (Project Euler 7), and as a part of this, my method to check whether or not an integer is prime references a vector:

fn main() {
let mut count: u32 = 1;
let mut num: u64 = 1;
let mut primes: Vec<u64> = Vec::new();
primes.push(2);


while count < 10001 {
num += 2;
if vectorIsPrime(num, primes) {
count += 1;
primes.push(num);
}
}
}


fn vectorIsPrime(num: u64, p: Vec<u64>) -> bool {
for i in p {
if num > i && num % i != 0 {
return false;
}
}


true
}

When I try to reference the vector, I get the following error:

error[E0382]: use of moved value: `primes`
--> src/main.rs:9:31
|
9 |         if vectorIsPrime(num, primes) {
|                               ^^^^^^ value moved here, in previous iteration of loop
|
= note: move occurs because `primes` has type `std::vec::Vec<u64>`, which does not implement the `Copy` trait

What do I have to do to primes in order to be able to access it within the vectorIsPrime function?

98641 次浏览

primes的值移动到函数 vectorIsPrime(BTWRust 按照约定使用 snake_case)。你还有其他选择,但最好的办法是借用矢量而不是移动它:

fn vector_is_prime(num: u64, p: &Vec<u64>) -> bool { … }

然后引用它:

vector_is_prime(num, &primes)

使用函数 vectorIsPrime()的当前定义,函数指定它需要参数的所有权,因为您要传递参数 按价值计算

When a function requires a parameter by value, the compiler will check if the value can be copied by checking if it implements the trait Copy.

  • 如果是这样,那么将复制该值(使用 memcpy)并将其赋给函数,而且您仍然可以继续使用原始值。
  • 如果没有,那么该值将被移动到给定的函数中,调用方之后就不能使用它了

这就是错误消息的含义。

然而,大多数函数不需要参数的所有权: 它们可以处理“借来的引用”,这意味着它们实际上并不拥有该值(例如,不能将其放入容器或销毁它)。

fn main() {
let mut count: u32 = 1;
let mut num: u64 = 1;
let mut primes: Vec<u64> = Vec::new();
primes.push(2);


while count < 10001 {
num += 2;
if vector_is_prime(num, &primes) {
count += 1;
primes.push(num);
}
}
}


fn vector_is_prime(num: u64, p: &[u64]) -> bool {
for &i in p {
if num > i && num % i != 0 {
return false;
}
}
true
}

函数 vector_is_prime()现在指定它只需要一个 slice,也就是一个借来的指向数组的指针(包括它的大小) ,您可以使用借来操作符 &从向量获得这个指针。

关于所有权的更多信息,我邀请您阅读书中关于 所有权的部分。

如我所说,Rust 是一种“面向价值”的语言,这意味着如果你像这样定义素数

let primes: Vec<u64> = …

它不是一个向量的引用。它实际上是一个存储 Vec<u64>类型的 价值的变量,就像任何 u64变量存储 u64值一样。这意味着如果将它传递给这样定义的函数

fn vec_is_prime(num: u64, vec: Vec<u64>) -> bool { … }

该函数将获得自己的 u64值和自己的 Vec<u64>值。

The difference between u64 and Vec<u64> however is that a u64 value can be easily copied to another place while a Vec<u64> value can only 让开 to another place easily. If you want to give the vec_is_prime function its own Vec<u64> value while keeping one for yourself in main, you have to duplicate it, somehow. That's what's clone() is for. The reason you have to be explicit here is because this operation is not cheap. That's one nice thing about Rust: It's not hard to spot expensive operations. So, you 可以 call the function like this

if vec_is_prime(num, primes.clone()) { …

但那不是你真正想要的。该函数不需要自己的 Vec<64>值。只是借用一下。在这种情况下,借款更加有效,也更加适用:

fn vec_is_prime(num: u64, vec: &Vec<u64>) -> bool { …

现在援引这一条款,需要“借款操作者”:

if vec_is_prime(num, &primes) { …

好多了。但我们还是可以改进的。如果一个函数只是为了读取它而借用一个 Vec<T>,那么最好是借用一个 &[T]:

fn vec_is_prime(num: u64, vec: &[u64]) -> bool { …

只是更一般而已。现在,您可以将 Vec 的一部分借给函数或其他完全不同的东西(不一定是 Vec,只要这个东西在内存中连续存储它的值,比如静态查找表)。还有一个好处是,由于强制规则,你不需要在呼叫网站上修改任何东西。您仍然可以使用 &primes作为参数调用这个函数。

对于 String&str,情况是一样的。String是用来存储字符串值的,意思是这种类型的变量 拥有的值。&str是用来借的。