gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 08:36:11 25 4
gpt4 key购买 nike

我在结构中有一个列表 ( 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


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

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();
}

最佳答案

for sprite in &mut self.sprites 行创建了一个跨越整个循环主体的 self.sprites 集合的可变借用。这意味着您不能在循环体内修改集合本身,因为这样做会导致循环失效。

当您尝试调用 self.sprites.remove(pos) 时,此调用导致 pos 之后的所有 Sprite 向前移动内存中的一个。这是被禁止的,因为您当前有一个对即将被删除的 Sprite 的引用,而且因为 pos + 1 处的 Sprite 将被跳过(remove 调用移动它向前移动一个,但迭代器将移动到它后面的槽)。

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

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
});

这遍历列表中的每个 Sprite ,更新它,然后返回一个条件,当 true 时,告诉 Vec 保留 Sprite ,当 false,告诉 Vec 删除它。

关于rust - 删除 Vec 产品第二次可变借用发生在这里,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56758886/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com