мне нужно нажать (Vec) члена структуры содержится, он также является структурой - PullRequest
1 голос
/ 30 июня 2019

Я пытаюсь добавить элемент структуры, которая сама является структурой.У меня есть классическая ошибка «не могу выйти из заимствованного контента».

Как мне обойти проблему

заранее спасибо.

use std::cell::RefCell;

pub struct Sprite {
    pub x: f32,
    pub y: f32,
}

impl Sprite {
    pub fn new(x: f32, y: f32) -> Sprite {
        let sprite: Sprite = Sprite { x: x, y: y };
        sprite
    }
}

pub struct Human {
    pub x: f32,
    pub y: f32,
    pub sprite: Sprite,
}

impl Human {
    pub fn new() -> Human {

        Human {
            x: 400.0,
            y: 300.0,
            sprite: Sprite::new(1.0, 1.0),
        }
    }
}

pub struct Game {
    pub human: Human,
    sprites: Vec<RefCell<Sprite>>,
}

impl Game {
    pub fn new() -> Game {
        let human = Human::new();

        Game {
            human: human,
            sprites: vec![],
        }
    }

    pub fn init(&mut self) {
        let  sprite  = self.human.sprite; //error : can not move out of borrowed content
        self.create_sprite(sprite);
    }

    fn create_sprite(&mut self, sprite: Sprite) {
        self.sprites.push(RefCell::new(sprite));
    }
}
fn main() {}

Я сделализменение, предложенное RLS, которое только сместило проблему.

Я также пытался изменить «время жизни» с аннотациями, оно тоже не сработало, но, возможно, я ошибаюсь.Я не очень хорошо знаю эту функцию.

REM: код purge for показывает ошибку и компилируется

1 Ответ

2 голосов
/ 30 июня 2019

Точно, значит, ваше:

let sprite = human.sprite 

Попытки отобрать право владения спрайтовым полем у человека, в котором оно определено. Это запрещено в ржавчине, так как это оставит висячую ссылку в структуре, если исходная ссылка будет уничтожена, или двойные ссылки, если скопирована. Оба небезопасны.
Использование заимствования допускает более простую семантику кода, но предполагается, что заимствования имеют конкретный срок службы, то есть, в общем, не оставайтесь без присмотра, поскольку вещь, из которой вы заимствуете, могла бы пережить ссылку на заимствование в противном случае. Последний вариант, который обычно используется, - это просто копирование данных, но, поскольку кажется, что вы хотите отслеживать полное состояние ваших спрайтов из нескольких мест, которые здесь не будут работать. Копирование данных не оставит ссылку на оригинал.

Есть способы обойти это в Rust. Итак, поскольку мне кажется, что вы хотите иметь возможность ссылаться на одну и ту же структуру Sprite из двух мест, вам нужно много обернуть здесь. Я добавил подсчет ссылок на ваш RefCell, эту обертку Rc можно затем клонировать и хранить в качестве ссылки на исходный Struct в нескольких местах. Затем RefCell предоставляет фактическую «блокировку» чтения-записи, позволяющую изменять данные из нескольких мест.

Посмотрите ниже и посмотрите, приближает ли это вас к вашему варианту использования:

use std::rc::Rc;
use std::cell::RefCell;

pub struct Sprite {
    pub x: f32,
    pub y: f32,
}

impl Sprite {
    pub fn new(x: f32, y: f32) -> Sprite {
        let sprite: Sprite = Sprite { x: x, y: y };
        sprite
    }
}

pub struct Human {
    pub x: f32,
    pub y: f32,
    pub sprite: Rc<RefCell<Sprite>>,
}

impl Human {
    pub fn new() -> Human {

        Human {
            x: 400.0,
            y: 300.0,
            sprite: Rc::new(RefCell::new(Sprite::new(1.0, 1.0))),
        }
    }
}

pub struct Game {
    pub human: Human,
    sprites: Vec<Rc<RefCell<Sprite>>>,
}

impl Game {
    pub fn new() -> Game {
        let human = Human::new();

        Game {
            human: human,
            sprites: vec![],
        }
    }

    pub fn init(&mut self) {
        let  sprite  = self.human.sprite.clone(); //error : can not move out of borrowed content
        self.create_sprite(sprite);
    }

    fn create_sprite(&mut self, sprite: Rc<RefCell<Sprite>>) {
        self.sprites.push(sprite);
    }
}
fn main() {}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...