假设我有以下代码:
use std::rc::Rc;
struct Struct {}
struct Pair {
first: Rc<Struct>,
second: Rc<Struct>
}
fn pair_lists(vec:Vec<Struct>) -> Vec<Pair> {
let mut pair = Vec::new();
for i in 0..vec.len() {
for j in i+1..vec.len() {
let new_pair = Pair {
first: Rc::new(vec[i]),
second: Rc::new(vec[j])
};
pair.push(new_pair);
}
}
pair
}
fn main() {
}
这将无法编译,因为在函数pair_lists
中,Rc::new
将获得vec
的所有权:
error[E0507]: cannot move out of index of `Vec<Struct>`
--> src/main.rs:15:32
|
15 | first: Rc::new(vec[i]),
| ^^^^^^ move occurs because value has type `Struct`, which does not implement the `Copy` trait
error[E0507]: cannot move out of index of `Vec<Struct>`
--> src/main.rs:16:33
|
16 | second: Rc::new(vec[j])
| ^^^^^^ move occurs because value has type `Struct`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0507`.
但是,我不想通过复制vec
的所有实例来创建开销;理想情况下,每个元素在内存中应该只有一个副本。
实现这一点的惯用方法是什么?
首先将vec
转换为Vec<Rc<Struct>>
,然后从中克隆Rc
s:
fn pair_lists(vec:Vec<Struct>) -> Vec<Pair> {
let vec: Vec<Rc<Struct>> = vec
.into_iter()
.map(Rc::new)
.collect();
let mut pair = Vec::new();
for i in 0..vec.len() {
for j in i+1..vec.len() {
let new_pair = Pair {
first: Rc::clone(&vec[i]),
second: Rc::clone(&vec[j]),
};
pair.push(new_pair);
}
}
pair
}
从vec创建pair也可以通过使用itertools
crate中的.tuple_windows()
来完成:
use itertools::Itertools;
fn pair_lists(vec:Vec<Struct>) -> Vec<Pair> {
vec.into_iter()
.map(Rc::new)
.tuple_windows()
.map(|(first, second)| Pair { first, second, })
.collect()
}