我正在用更小的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
可变?
2条答案
按热度按时间zrfyljdw1#
不同之处在于
append
将每个项目从一个Vec
移动到另一个Vec
,extend_from_slice
将克隆每个项目。就性能而言,在您的情况下,即使
f64
is the same的克隆和副本,append
使用的std::ptr::copy_nonoverlapping等效于memcpy
,而extend_from_slice
迭代和克隆每个项目,两者之间也有细微的差异。当源
Vec
包含具有动态内存的值,并且希望避免克隆(如String
)带来的重新分配,或者源Vec
很大时,性能才是真正重要的。append
的源代码需要是可变的,因为它通过移出值并将其长度设置为0来改变其内部状态。我认为
concat
是一种不同的用例,其中源结构体的数量未知,并且由于它需要迭代所有项,因此性能可能会更差。dy2hfwbg2#
append()
清空了源Vec
s,因此需要将它们作为&mut
。它不移动它们,因为您可能仍然希望使用它们的分配内存。在性能方面,所有方法都使用普通的
memcpy()
-append()
,因为它会移动项,而其他方法则专门为Copy
项使用简单的副本。然而,append()
和extend_from_slice()
每次添加时都会将向量增长两倍,而concat()
会提前计算所需的容量,因此速度可能更快。