移除Vec产品第二次可变借用发生在这里

时间:2019-06-25 17:04:23

标签: rust

我在结构中有一个列表(sprites: Vec<RefCell<Sprite>>

我必须添加并删除对象,添加没有问题,但是无法删除

添加对象

pub fn _clean() {}
    fn create_sprite(&mut self, x: f32, y: f32) {
        let src_rect = Rect::new(0, 0, 9, 9);
        let mut sprite = Sprite::new(0, x, y, src_rect);

        self.sprites.push(RefCell::new(sprite));
        println!("{}", self.sprites.len());
    }

删除对象

let mut pos: usize = 0;
        for sprite in &mut self.sprites {
            sprite.borrow_mut().x += 1.0;
            // collision sprite shoot
            if sprite.borrow_mut().x > (self.map.nbr_column as u32 * self.map.tile_wight) as f32 {
                println!("shoot out {}", pos);
                self.sprites.remove(pos);
                //self.remove_sprite(pos);
            }
            pos += 1;
        }

如果我做pop而不是remove的同上


我清理了代码以生成可执行的minumun代码

use std::cell::RefCell;

pub struct Sprite {
    pub index: usize,
    pub x: f32,
    pub y: f32,
    pub vx: f32,
    pub vy: f32,
}

impl Sprite {
    pub fn new(index: usize, x: f32, y: f32) -> Sprite {
        let mut sprite: Sprite = Sprite {
            index: index,
            x: x,
            y: y,
            vx: 0.0,
            vy: 0.0,
        };
        sprite
    }
}

pub struct Game {
    sprites: Vec<RefCell<Sprite>>,
    map: f32,
}

impl Game {
    pub fn new() -> Game {
        Game {
            sprites: vec![],
            map: 30.0,
        }
    }

    pub fn update(&mut self) {
        let mut pos: usize = 0;
        self.sprites.retain(|s| {
            // s is &RefCell<Sprite>
            s.borrow_mut().x += 1.0;
            s.borrow().x <= self.map
        });
        println!("{}", self.sprites.len());
    }

    fn create_sprite(&mut self, x: f32, y: f32) {
        let mut sprite = Sprite::new(0, x, y);

        self.sprites.push(RefCell::new(sprite));
        println!("{}", self.sprites.len());
    }

    pub fn handle_event(&mut self) {
        self.create_sprite(10.0, 10.0);
        self.create_sprite(20.0, 10.0);
        self.create_sprite(30.0, 10.0);
        self.create_sprite(40.0, 10.0);
        self.create_sprite(50.0, 10.0);
        self.create_sprite(60.0, 10.0);
    }
}

fn main() {
    let mut the_game = Game::new();

    the_game.handle_event();
    the_game.update();
}

2 个答案:

答案 0 :(得分:0)

let array1 = [{id:"1",title:"Writing"},{id:"2",title:"Singing"},{id:"3",title:"Dance"}]; let array2 = [{tags: "1",title: "USA",type: "text"},{tags: "1,2,3",title: "Japan",type: "image"},{tags: "2,3",title: "Japan",type: "image"}]; let obj = array1.reduce((a,c) => Object.assign(a, {[c.id] : c.title}), {}); array2.forEach(o => o.tags = o.tags.split(",").map(v => obj[v]).join(",")); console.log(array2);行创建了for sprite in &mut self.sprites集合的可变借项,该集合跨越整个循环主体。这意味着您无法在循环体内修改集合本身,因为这样做会导致循环无效。

当您尝试调用self.sprites时,此调用 将导致self.sprites.remove(pos)之后的所有子画面在内存中向前移动一个。之所以禁止这样做,是因为您当前有一个将要删除的精灵的引用,并且还因为pos处的精灵将被跳过(pos + 1调用将其向前移动一个,但是迭代器将移至其后的插槽中。)

Rust提供一种执行循环主体尝试执行的操作的方法:Vec::retain方法。

remove

这会遍历列表中的每个精灵,然后对其进行更新,然后返回一个条件,当self.sprites.retain(|s| { // s is &RefCell<Sprite> s.borrow_mut().x += 1.0; sprite.borrow_mut().x <= (self.map.nbr_column as u32 * self.map.tile_wight) as f32 }); 告诉true保留精灵时,而Vec告诉false将其删除。

答案 1 :(得分:0)

感谢您的帮助,此代码有效

...
let map_width = (self.map.nbr_column as u32 * self.map.tile_wight) as f32;
self.sprites.retain(|s| {
    // s is &RefCell<Sprite>
    s.borrow_mut().x += 1.0;
    s.borrow().x <= map_width
});
...