参考和生命周期

时间:2014-08-13 11:23:02

标签: rust

我刚刚开始尝试使用Rust,并希望将这个简单的C ++程序转换为Rust:

#include <iostream>
#include <vector>
#include <stdint.h>

using namespace std;

struct Game;

struct Player {
  Player(Game* game, uint32_t health) : game(game), health(health) {
  }

  uint32_t health;
  Game* game;
};

struct Game {
  Player& new_player() {
    players.emplace_back(this, 100);
    return players.back();
  }

  vector<Player> players;
};


int main() {
  Game g;
  g.new_player().health -= 10;
  g.new_player().health -= 20;

  for (auto p : g.players) {
    cout << "player health = " << p.health << endl;
  }

  return 0;
}

这是我的hacky Rust尝试:

struct Player<'a> {
  health: i32,
  game: &'a mut Game<'a>
}

struct Game<'a> {
  players: Vec<Player<'a>>
}

impl <'a> Game<'a> {
  fn new() -> Game<'a> {
    Game { players: Vec::new() }
  }

  fn new_player(&'a mut self) -> &'a mut Player<'a> {
    unsafe {
      // Ugly unsafe hack to fix compiler error
      let ps: *mut Game<'a> = self;
      self.players.push(Player { health: 100, game: &mut *ps });
      self.players.mut_last().unwrap()
    }
  }
}

fn main() {
  let mut g = Game::new();
  g.new_player().health -= 10;

  // Compiler error about multiple borrows
  g.new_player().health -= 20;

  // Compiler error about multiple borrows
  for p in g.players.mut_iter() {
    println!("player health = {}", p.health);
  }
}

然而,我使用不安全的代码(我希望这是不必要的)并遇到引用和生命周期的问题,我真的不知道如何修复。在Rust中编写此代码的惯用方法是什么?或者Rust类型系统目前是否过于局限,无法以安全的方式表达它?

顺便说一句,我正在使用&#34; rustc 0.12.0-每晚(6bb72600c 2014-08-05 00:01:28 +0000)&#34;。

1 个答案:

答案 0 :(得分:0)

对于您同时对某个对象进行多次可变引用并不合适,但是您在不安全的代码中导致了这种情况。这是一个等待发生的内存安全漏洞,因为你打破了关于可变引用的不变量。

如果您希望能够从多个地方访问它,则需要使用Rc<RefCell<Game>>之类的内容(将Player Weak<RefCell<Game>>内的内容设为Game)。 ll仍然需要在运行时确保您不会一次对基础Game进行两次可变引用。

如果您可以避免在Player中存储对{{1}}的引用,那也可以解决问题。