如何在Rust中修改向量的元素?

如何在Rust中修改向量的元素?,rust,Rust,我试图将对Vec(一个切片)的不可变引用传递给一个函数,该函数将用递增的值填充Vec,然后再次对其进行迭代,将其中的一些值替换为零 我的想法是向量是不可变的(向量的数据类型和大小永远不会改变),但是向量的内容应该是可变的整数引用。或者它们应该是整数本身的实际值(而不是引用) 事实证明,这是一项艰巨的任务。。我读过关于易变性和借用的书,我觉得我对这方面的理解还不错。我对C语言中引用、去引用、指针等的工作原理也有一个粗略的了解,但我认为我正在与Rust的语法作斗争来实现这一点 我是不是想错了?在Ru

我试图将对
Vec
(一个切片)的不可变引用传递给一个函数,该函数将用递增的值填充
Vec
,然后再次对其进行迭代,将其中的一些值替换为零

我的想法是向量是不可变的(向量的数据类型和大小永远不会改变),但是向量的内容应该是可变的整数引用。或者它们应该是整数本身的实际值(而不是引用)

事实证明,这是一项艰巨的任务。。我读过关于易变性和借用的书,我觉得我对这方面的理解还不错。我对C语言中引用、去引用、指针等的工作原理也有一个粗略的了解,但我认为我正在与Rust的语法作斗争来实现这一点

我是不是想错了?在Rust中,创建一个潜在巨大的
Vec
副本,对其进行操作并返回它是否更为惯用

这是我到目前为止的代码(未编译,错误很多):

#![特征(迭代器步进)]
第n次发布(n:usize){
让大小:usize=(2作为f64*n作为f64*(n作为f64).ln())作为usize;
//设定围网的上限。
让size_sqrt:usize=(大小为f64).sqrt().ceil()为usize;
让nums:Vec=Vec::具有_容量(大小);
筛子(单位、尺寸和尺寸);
}
fn筛(nums:[&mut usize],尺寸:&usize,尺寸:&usize){
对于尺寸为0..*的i{
nums[i]=i;
}
对于num中的num{
如果num<2{
继续;
}否则,如果数量>*大小{
打破
}
对于x英寸(num.pow(2)…大小)。步进方式(*num){
nums[x]=0;
}
}
}
我的想法是向量是不可变的(向量的数据类型和大小永远不会改变),但是向量的内容应该是可变的整数引用。或者它们应该是整数本身的实际值(而不是引用)

引用(
&'a T
&'a mut T
)只能引用由另一个值拥有的值。引用不能拥有其引用对象

如果希望函数对集合中不一定连续的某些整数进行操作,那么最好构建一个整数引用向量。但是,根据您的代码示例,情况似乎并非如此;向量拥有整数将更简单、更容易。这意味着向量本身需要是可变的。但是,如果要确保函数不尝试更改向量的大小,则该函数可以接受可变整数片
&mut[usize]
,而不是向量的可变引用(
&mut-Vec

在Rust中,创建一个潜在巨大的
Vec
副本,对其进行操作并返回它是否更为惯用

这取决于以后是否需要再次使用原始的
Vec
。如果不这样做,那么将
Vec
就地突变会更有效。如果在某些情况下只需要保留原始的
Vec
,而在其他情况下则不需要,则可以事先
clone()
Vec。如果您每次都需要原始的
Vec
,那么返回新的
Vec
可能会更有效,尤其是如果您可以使用从迭代器填充它,因为这将尝试提前分配正确的大小,并且只分配
Vec
中的每个值一次


考虑到所有这些,下面是我将如何编写您的代码。请注意,我必须将
sieve
中的主循环更改为不直接迭代
nums
,因为这会导致借用冲突–for的
循环需要在
nums
上借用,但赋值
nums[x]
还将尝试在
nums
上进行可变借用,而另一个借用处于活动状态。我还将
&usize
参数更改为
usize
,因为对小型可复制类型(如原始整数)使用引用没有任何好处(事实上,它可能会稍微慢一点)

#![特征(迭代器步进)]
第n次发布(n:usize){
让大小:usize=(2.0*n为f64*(n为f64).ln())为usize;
//设定围网的上限。
让size_sqrt:usize=(大小为f64).sqrt().ceil()为usize;
让mut nums:Vec=Vec![0;大小];
筛子(多个数量、尺寸、尺寸);
}
fn筛(nums:&mut[usize],尺寸:usize,尺寸:usize){
对于0.号的i{
nums[i]=i;
}
对于0.号的i{
设num=nums[i];
如果num<2{
继续;
}
如果num>size\u sqrt{
打破
}
对于x英寸(num.pow(2)…大小)。步进(num){
nums[x]=0;
}
}
}

是的,它是惯用的。也有一些时候不是这样。谢谢你,至少我知道我在正确的轨道上。我还意识到我希望获得更多与我的问题相关的信息,因此我将修改问题
let mut v=vec![1, 2, 3]; v[0]=42(是的,我知道我看起来很迟钝,但我试图看看我是否能找出真正的潜在问题)。我认为OP中的重要问题是“我的想法是向量是不可变的(向量的数据类型和大小永远不会改变)但是向量的内容应该是整数的可变引用。或者它们应该是整数本身的实际值(而不是引用)?“我觉得你的第一条思路很奇怪,而你的第二个选择(向量包含整数)是我们大多数人都会做的。谢谢你周到的回答。这消除了我的多个误解,特别是关于可变向量和可变引用的不可变向量的部分。
#![feature(iterator_step_by)]

pub fn nth(n: usize) {
    let size: usize = (2 as f64 * n as f64 * (n as f64).ln()) as usize;
    // Set an upper bound for seiving.
    let size_sqrt: usize = (size as f64).sqrt().ceil() as usize;
    let nums: Vec<&mut usize> = Vec::with_capacity(size);
    sieve(nums, &size, &size_sqrt);
}

fn sieve(nums: [&mut usize], size: &usize, size_sqrt: &usize) {
    for i in 0..*size {
        nums[i] = i;
    }
    for num in nums {
        if num < 2 {
            continue;
        } else if num > *size_sqrt {
            break;
        }
        for x in (num.pow(2)..size).step_by(*num) {
            nums[x] = 0;
        }
    }
}
#![feature(iterator_step_by)]

pub fn nth(n: usize) {
    let size: usize = (2.0 * n as f64 * (n as f64).ln()) as usize;
    // Set an upper bound for seiving.
    let size_sqrt: usize = (size as f64).sqrt().ceil() as usize;
    let mut nums: Vec<usize> = vec![0; size];
    sieve(&mut nums, size, size_sqrt);
}

fn sieve(nums: &mut [usize], size: usize, size_sqrt: usize) {
    for i in 0..size {
        nums[i] = i;
    }

    for i in 0..size {
        let num = nums[i];
        if num < 2 {
            continue;
        }

        if num > size_sqrt {
            break;
        }

        for x in (num.pow(2)..size).step_by(num) {
            nums[x] = 0;
        }
    }
}