英文:
Move boxed values from one Vec to another
问题
I'd like to move some Boxed values from one Vec to another, but I can't figure out if this is possible or whether I'm thinking about it wrong.
So far, my smallest example of the problem is:
#[derive(Debug)]
pub struct B {
    value: usize
}
fn main() {
    let v1: Vec<_> = (1..3).map(|i| Box::new(B { value: i })).collect();
    let v2: Vec<Box<B>> = v1.iter().map(|b| *b).collect();
    println!("{v2:?}");
}
Which gives the error:
error[E0507]: cannot move out of `*b` which is behind a shared reference
 --> src/main.rs:8:45
  |
8 |     let v2: Vec<Box<B>> = v1.iter().map(|b| *b).collect();
  |                                             ^^ move occurs because `*b` has type `Box<B>`, which does not implement the `Copy` trait
I've tried various (but possibly incorrect) methods of trying to move the contents of the Box with std::mem::swap and friends, but haven't managed to get that right.
For clarity, I want to avoid copying the Bs - in reality they are large. I haven't experimented with an Rc, and ideally I'd avoid that. v1 is effectively consumed when it is mapped into v2.
As shown above, the example is pretty uninteresting, in the "real" case, v1 is a Vec of 2-tuples, and I'd like to map it to a Vec of 3-tuples with an extra element derived from the first two.
I'm aware I don't need all the type annotation, but that helps check I'm getting what I want. For a while I thought I had succeeded, but was actually getting a Vec<&Box<B>> (or similar, don't take my exact word for it).
Does anyone have any insight as to how to do this, or how I can approach the problem differently? Thanks!
英文:
I'd like to move some Boxed values from one Vec to another, but I can't figure out if this is possible or whether I'm thinking about it wrong.
So far, my smallest example of the problem is:
#[derive(Debug)]
pub struct B {
    value:      usize
}
fn main() {
    let v1: Vec<_> = (1..3).map(|i| Box::new(B{ value: i})).collect();
    let v2: Vec<Box<B>> = v1.iter().map(|b| *b).collect();
    println!("{v2:?}");
}
Which gives the error:
error[E0507]: cannot move out of `*b` which is behind a shared reference
 --> src/main.rs:8:45
  |
8 |     let v2: Vec<Box<B>> = v1.iter().map(|b| *b).collect();
  |                                             ^^ move occurs because `*b` has type `Box<B>`, which does not implement the `Copy` trait
I've tried various (but possibly incorrect) methods of trying to move the contents of the Box with std::mem::swap and friends, but haven't managed to get that right.
For clarity, I want to avoid copying the B's - in reality they are large.  I haven't experimented with an Rc, and ideally I'd avoid that.  v1 is effectively consumed when it is mapped into v2.
As shown above, the example is pretty uninteresting, in the "real" case, v1 is a Vec of 2-tuples, and I'd like to map it to a Vec of 3-tuples with an extra element derived from the first two.
I'm aware I don't need all the type annotation, but that helps check I'm getting what I want.  For a while I thought I had succeeded, but was actually getting a Vec<&Box<B>> (or similar, don't take my exact word for it).
Does anyone have any insight as to how to do this, or how I can approach the problem differently? Thanks!
答案1
得分: 3
如果您想 消耗 原始向量,您应该使用 into_iter 而不是 iter,后者只提供共享引用:
let v1: Vec<_> = (1..3).map(|i| Box::new(B{ value: i})).collect();
let v2: Vec<Box<B>> = v1.into_iter().collect();
英文:
If you want to consume the orginial vector you want into_iter not iter which only gives you shared references:
let v1: Vec<_> = (1..3).map(|i| Box::new(B{ value: i})).collect();
let v2: Vec<Box<B>> = v1.into_iter().collect();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论