rust - 我需要推送 (Vec) 包含的结构成员,他也是一个结构

标签 rust

我正在尝试添加本身就是结构的结构的成员。我有经典错误“不能搬出借来的内容”。

我怎样才能解决这个问题

提前致谢。

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 : 代码被清除以显示错误并编译

最佳答案

对,所以你的:

let sprite = human.sprite 

试图将 sprite 字段的所有权从定义它的人手中夺走。 这在 Rust 中是被禁止的,因为如果原始引用被破坏,它会在结构中留下悬空引用,或者如果被复制,则会留下双重引用。两者都不安全。
使用借用允许更简单的代码语义,但借用应该具有特定的生命周期,即通常不会停留,因为您借用的东西可能比借用引用长寿。 通常使用的最后一个选项只是复制数据,但因为您似乎想从这里无法工作的几个地方跟踪 Sprite 的完整状态。复制数据不会留下对原始数据的引用。

在 Rust 中有解决这个问题的方法。 所以,因为在我看来你希望能够从两个位置引用相同的 Sprite-struct,所以你需要在此处进行大量包装。 我已将引用计数添加到您的 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() {}

关于rust - 我需要推送 (Vec) 包含的结构成员,他也是一个结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56823465/

相关文章:

iterator - 如何编写返回对自身的引用的迭代器?

rust - 为什么借用仍然保留在 if let 的 else block 中?

file - 无法将文件导入 Rust 中的另一个文件

error-handling - 我需要帮助重构 Rust 中的错误处理

rust - 外部模块中不可见的通用特征

rust - `if` 具有自有和借入值的分支,没有 let 绑定(bind)

rust - 如何使用共享捕获变量的多个闭包编译 Rust 0.10?

arrays - 在 GoLang 和 Rust 中初始化字符串数组

rust - 如何在 Rust 中将两个 i16 相加或相乘形成一个 i32 而不会溢出?

rust - StreamExt .scan()方法上的“expected bound lifetime parameter, found concrete lifetime”