借用的值不够长,尝试暴露迭代器而不是数据的具体Vec表示

时间:2015-11-29 22:34:01

标签: rust borrow-checker

我有一个表示数据网格的结构,以及行和列的访问器。我试图为返回迭代器而不是Vec的行和列添加访问器。

use std::slice::Iter;

#[derive(Debug)]
pub struct Grid<Item : Copy> {
    raw : Vec<Vec<Item>>
}

impl <Item : Copy> Grid <Item>
{
    pub fn new( data: Vec<Vec<Item>> ) -> Grid<Item> {
        Grid{ raw : data }
    }
    pub fn width( &self ) -> usize {
        self.rows()[0].len()
    }
    pub fn height( &self ) -> usize {
        self.rows().len()
    }
    pub fn rows( &self ) -> Vec<Vec<Item>> {
        self.raw.to_owned()
    }
    pub fn cols( &self ) -> Vec<Vec<Item>> {
        let mut cols = Vec::new();
        for i in 0..self.height() {
            let col = self.rows().iter()
                        .map( |row| row[i] )
                        .collect::<Vec<Item>>();
            cols.push(col);
        }
        cols
    }

    pub fn rows_iter( &self ) -> Iter<Vec<Item>> {
        // LIFETIME ERROR HERE
        self.rows().iter()
    }

    pub fn cols_iter( &self ) -> Iter<Vec<Item>> {
        // LIFETIME ERROR HERE
        self.cols().iter()
    }
}

rows_itercols_iter这两个函数都有同样的问题:error: borrowed value does not live long enough。我已经尝试了很多东西,但是把它简化回到最简单的事情上来发布。

2 个答案:

答案 0 :(得分:2)

您可以使用返回into_iter的方法std::vec::IntoIter。函数iter通常只借用迭代的数据源。 into_iter拥有数据源的所有权。因此,矢量将与实际数据一样长。

pub fn cols_iter( &self ) -> std::vec::IntoIter<Vec<Item>> {
    self.cols().intoiter()
}

但是,我认为你的网格类型的设计可以大大改进。总是克隆一个向量并不是一件好事(仅举一个问题)。

答案 1 :(得分:1)

迭代器只包含对原始数据结构的借用引用;他们不接受它的所有权。因此,向量必须比该向量上的迭代器长寿。

rowscols分配并返回新的Vecrows_itercols_iter正在尝试在临时Vec上返回迭代器。在Vecrows_iter返回之前,此cols_iter将被取消分配。这意味着必须在函数返回之前释放Vec上的迭代器。但是,您试图从函数返回迭代器,这将使迭代器的活动时间长于函数的结尾。

根本无法使rows_itercols_iter按原样编译。我认为这些方法根本就没有必要,因为您已经提供了公开rowscols方法。