Rust 我要怎么做才能解决“a”;“移动值”的使用;错误?

Rust 我要怎么做才能解决“a”;“移动值”的使用;错误?,rust,Rust,我正在尝试计算Rust(Project Euler 7)中的10001st素数,作为其中的一部分,我检查整数是否为素数的方法引用了向量: 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

我正在尝试计算Rust(Project Euler 7)中的10001st素数,作为其中的一部分,我检查整数是否为素数的方法引用了向量:

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
}
fn main(){
让mut计数:u32=1;
设mut num:u64=1;
让mut素数为:Vec=Vec::new();
素数推(2);
当计数小于10001时{
num+=2;
if向量名称(num,primes){
计数+=1;
primes.push(num);
}
}
}
fn矢量名称(num:u64,p:Vec)->bool{
因为我在p{
如果num>i&&num%i!=0{
返回false;
}
}
真的
}
当我尝试引用向量时,我得到以下错误:

错误[E0382]:使用移动值:`primes`
-->src/main.rs:9:31
|
9 |如果向量空间(num,素数){
|^^^^^值在循环的上一次迭代中移动到此处
|
=注意:之所以发生移动,是因为'primes'的类型为'std::vec::vec',而该类型不实现'Copy'特性

为了能够在
向量集
函数中访问它,我必须对
素数
做些什么?

素数
的值移动到函数
向量集
(顺便说一句,按照惯例使用
蛇壳
)。您还有其他选择,但最好的选择是借用向量,而不是移动向量:

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

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

当函数需要参数by value时,编译器将通过检查是否实现trait
Copy
来检查是否可以复制该值

  • 如果是,则复制该值(使用memcpy)并将其提供给函数,并且您仍然可以继续使用原始值
  • 如果没有,则将该值移动到给定的函数,并且调用方以后不能使用它
这就是您收到的错误消息的含义

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

fn main(){
让mut计数:u32=1;
设mut num:u64=1;
让mut素数为:Vec=Vec::new();
素数推(2);
当计数小于10001时{
num+=2;
如果向量是素数(num,&primes){
计数+=1;
primes.push(num);
}
}
}
fn向量是素数(num:u64,p:&[u64])->bool{
在p&i中{
如果num>i&&num%i!=0{
返回false;
}
}
真的
}
函数
vector\u is_prime()
现在指定它只需要一个片,即一个指向数组(包括其大小)的借用指针,您可以使用借用操作符
从向量中获得该指针


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

如我所说,生锈是一种“面向价值”的语言。这意味着如果您定义这样的素数

let primes: Vec<u64> = …
fn vec_is_prime(num: u64, vec: Vec<u64>) -> bool { … }
if vec_is_prime(num, primes.clone()) { …
该函数将获得自己的
u64
值和自己的
Vec

然而,
u64
Vec
之间的区别在于,
u64
值可以很容易地复制到另一个地方,而
Vec
值只能很容易地移动到另一个地方。如果你想给
Vec_is_prime
函数自己的
Vec
值,同时为自己保留一个值,你必须我必须以某种方式复制它。这就是
clone()
的目的。在这里你必须明确的原因是这个操作并不便宜。Rust的一个好处是:不难发现昂贵的操作。因此,你可以像这样调用函数

let primes: Vec<u64> = …
fn vec_is_prime(num: u64, vec: Vec<u64>) -> bool { … }
if vec_is_prime(num, primes.clone()) { …
但事实上,这并不是您真正想要的。函数不需要自己的
Vec
值。它只需要借用一小段时间。在这种情况下,借用更有效、更适用:

fn vec_is_prime(num: u64, vec: &Vec<u64>) -> bool { …
更好。但是我们仍然可以改进它。如果函数想借用一个
Vec
,只是为了读取它,那么最好使用一个
&[T]

fn vec_is_prime(num: u64, vec: &[u64]) -> bool { …
现在,您可以将Vec的某一部分借给函数或其他完全的东西(不一定是
Vec
,只要该东西在内存中连续存储其值,如静态查找表)。另一个好处是,由于协作规则,您不需要在调用站点更改任何内容。您仍然可以使用
&primes
作为参数调用此函数


对于
String
&str
来说,情况是一样的。
String
用于存储字符串值,因为这种类型的变量拥有该值。
&str
用于借用它们。

一个小细节:在迭代时,正如@Vaelden所写的,迭代变量
i
需要是w写为
&i
@mjkaufer:这是一种可能性,是的。另一种可能是在使用
i
的地方取消引用。迭代借用的片段会得到借用的元素。如果不这样做,则需要元素类型为
Copy
Clone
。如果在for循环中使用
&i
,则
i
将是向量元素的副本。为什么
i
in
for&i in p{
需要一个
&
在它前面吗?代码在没有它的情况下会抛出一个编译错误,我很好奇为什么。@mjkaufer,这意味着
I
是一个引用,因此,在循环中,我将是值,而不是引用。如果你忽略它,你在进行比较时需要*I。@mjkaufer,这意味着
I
是一个引用,因此,在向量_is_prime不正确,它应该是:
if num>i&&num%i==0