Rust 在结构中实例化2d Vec?

Rust 在结构中实例化2d Vec?,rust,Rust,当使用构造函数返回新的struct对象时,我在实例化vec时遇到问题。我尝试过不正确地使用collect的语法,可能会导致大量编译器错误 fn main() { let level = Level::new(); } struct Level { tiles: Vec<Vec<Tile>> } struct Tile { idx: i32 } impl Level { fn new() -> Level { Le

当使用构造函数返回新的struct对象时,我在实例化vec时遇到问题。我尝试过不正确地使用collect的语法,可能会导致大量编译器错误

fn main() {
    let level = Level::new();
}

struct Level {
    tiles: Vec<Vec<Tile>>
}

struct Tile {
    idx: i32
}

impl Level {
    fn new() -> Level {
        Level {
            tiles: {
            let mut t = Vec::new();
            let mut t2 = Vec::new();
            for x in range(0, 80) {
                for y in range(0, 24) {
                    t2.push(Tile::new(x, y));
                }
                t.push(t2);
            }
            t
        }
    }
}

impl Tile {
    fn new(x: i32, y: i32) -> Tile {
        Tile { pos: Point { x: x, y: y } }
    }
}

struct Point {
    x: i32,
    y: i32
}
我发现以下错误:

src/game/dungeon/level/mod.rs:47:25: 47:27 error: use of moved value: `t2`
src/game/dungeon/level/mod.rs:47                 t2.push(Tile::new(x, y));
                                                     ^~
src/game/dungeon/level/mod.rs:49:28: 49:30 note: `t2` moved here because it has type `collections::vec::Vec<game::dungeon::level::Tile>`, which is non-copyable
src/game/dungeon/level/mod.rs:49                     t.push(t2);
                                                        ^~
src/game/dungeon/level/mod.rs:49:28: 49:30 error: use of moved value: `t2`
src/game/dungeon/level/mod.rs:49                     t.push(t2);
                                                        ^~
src/game/dungeon/level/mod.rs:49:28: 49:30 note: `t2` moved here because it has type `collections::vec::Vec<game::dungeon::level::Tile>`, which is non-copyable
src/game/dungeon/level/mod.rs:49                     t.push(t2);
                                                        ^~

是的,你做得不对。顺便说一句,C/C++中的类似代码也不正确

        let mut t = Vec::new();
        let mut t2 = Vec::new();
        for x in range(0, 80) {
            for y in range(0, 24) {
                t2.push(Tile::new());
            }
            t.push(t2);
        }
问题是,你总是把同样的t2推到内环,然后你总是把同样的t2推到t。后者违反了所有权语义,因此Rust编译器正确地告诉您使用移动值

惯用的方法是使用迭代器,它可以如下所示:

(0..80).map(|_| (0..24).map(|_| Tile::new()).collect()).collect()
如果需要访问索引,可以使用映射闭包参数:

(0..80).map(|x| (0..24).map(|y| Tile::new(x, y)).collect()).collect()

编译器应该自动推断所需的收集结果类型。

Vladimir的回答非常好,但是我感觉函数式可能会在这里隐藏错误

你实际上离解决方案不远;问题很简单,您不能在外部循环的每次迭代中重用相同的t2。因此,最简单的转换是在外循环内创建t2:

impl Level {
    fn new() -> Level {
        Level {
            tiles: {
            let mut t = Vec::new();
            for x in range(0, 80) {
                let mut t2 = Vec::new(); // Moved!
                for y in range(0, 24) {
                    t2.push(Tile::new(x, y));
                }
                t.push(t2);
            }
            t
        }
    }
}

你一直在使用什么语法?我会用我刚刚尝试过的内容更新帖子。错误是什么?用errorsWell再次更新帖子,功能风格现在是惯用的方法,也就是说,在将来大部分代码都会这样编写:@VladimirMatveev:我同意,而且它也更整洁、更简洁;然而,我担心这可能比OP的当前代码提高了太多,所以我更愿意在建议改变风格的基础上指出当前的问题是什么,或者我的意思是,让你建议改变风格。我最终使用了Vladimir的解决方案,但你的解决方案帮助我准确地理解了我做错了什么-谢谢!