rust 向量〈>推送和连接与附加与从切片扩展

w41d8nur  于 2023-01-21  发布在  其他
关注(0)|答案(2)|浏览(154)

我正在用更小的Vec<f64>构造一个Vec<f64>,不太明白哪种方法是正确的。
以下是三次尝试,并对每一次尝试进行了评论:

fn main() {
    // this vector will be getting changed so is mutable
    let mut a:Vec<Vec<f64>> = vec![];

    // these won't be getting changed, they gets appended to `a`
    let b = vec![0.0, 1.0];
    let c = vec![2.0, 3.0];

    a.push(b);
    a.push(c);
    
    // and then the vector gets flattened into the form that I require:
    dbg!(a.concat());

    // however, if I want a single level vector constructed from other vectors
    let mut d:Vec<f64> = vec![];

    // b and c have to be mutable, why is that?
    // their contents don't change?
    // why can't they just be consumed?
    let mut e = vec![0.0, 1.0];
    let mut f = vec![2.0, 3.0];

    d.append(&mut e);
    d.append(&mut f);

    dbg!(d);

    // another method is to extend from slice
    // does this have performance problems compared to the other methods due
    // to the copying required?
    let mut g:Vec<f64> = vec![];
    
    let h = vec![0.0, 1.0];
    let i = vec![2.0, 3.0];

    g.extend_from_slice(&h);
    g.extend_from_slice(&i);

    dbg!(g);

}

输出:

[src/main.rs:15] a.concat() = [
    0.0,
    1.0,
    2.0,
    3.0,
]
[src/main.rs:28] d = [
    0.0,
    1.0,
    2.0,
    3.0,
]
[src/main.rs:46] g = [
    0.0,
    1.0,
    2.0,
    3.0,
]

我倾向于extend_from_slice,因为它向代码的读者传达向量h&i不会改变。
但我的问题是:复制是否会影响性能?是否有一种方法可以在追加时只使用数据,而不使向量e & f可变?

zrfyljdw

zrfyljdw1#

不同之处在于append将每个项目从一个Vec移动到另一个Vecextend_from_slice将克隆每个项目。
就性能而言,在您的情况下,即使f64is the same的克隆和副本,append使用的std::ptr::copy_nonoverlapping等效于memcpy,而extend_from_slice迭代和克隆每个项目,两者之间也有细微的差异。
当源Vec包含具有动态内存的值,并且希望避免克隆(如String)带来的重新分配,或者源Vec很大时,性能才是真正重要的。
append的源代码需要是可变的,因为它通过移出值并将其长度设置为0来改变其内部状态。
我认为concat是一种不同的用例,其中源结构体的数量未知,并且由于它需要迭代所有项,因此性能可能会更差。

dy2hfwbg

dy2hfwbg2#

append()清空了源Vec s,因此需要将它们作为&mut。它不移动它们,因为您可能仍然希望使用它们的分配内存。
在性能方面,所有方法都使用普通的memcpy()-append(),因为它会移动项,而其他方法则专门为Copy项使用简单的副本。然而,append()extend_from_slice()每次添加时都会将向量增长两倍,而concat()会提前计算所需的容量,因此速度可能更快。

相关问题