首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >锈蚀和旧迭代器模式下的寿命

锈蚀和旧迭代器模式下的寿命
EN

Stack Overflow用户
提问于 2014-09-03 22:36:25
回答 1查看 534关注 0票数 4

我发现锈病打破了一些旧代码,我决心要修复它。可悲的是,似乎生命周期引用已经发生了很大的变化,一些奇怪的事情正在发生。字段Counter.data是不相关的,它只是用来表明我使用了一些数据,并且它引用了一些通用的东西。

以下是代码:

代码语言:javascript
复制
struct Counter <'c, T: 'c> {
    val: u32,
    data: &'c T
}

struct CounterIterator<'c, T:'c> {
    iter: &'c mut Counter<'c, T>,
    num: u32
}

impl<'r, T> Iterator<u32> for CounterIterator<'r, T> {
    fn next(&mut self) -> Option<u32> {
        if self.num  == 0 {
            None
        } else {
            self.num -= 1;
            self.iter.incr()
        }
    }
}

impl<'c, T> Counter <'c, T> {
    fn new(dataz: &'c T) -> Counter<'c, T> {
        Counter {
            val: 0u32,
            data: dataz
        }
    }

    fn incr(&mut self) -> Option<u32> {
        self.val += 1;
        println!("{}", self.val);
        Some(self.val)
    }

    fn iter(&'c mut self, num: u32) -> CounterIterator<'c, T> {
        CounterIterator {
            iter: self,
            num: num
        }
    }
}

fn main() {
    let val = 11u;
    let mut cnt = Counter::new(&val);
    for i in range(0,2u) {
        cnt.incr();
    }

    for i in cnt.iter(3) {

    }

    cnt.incr(); // <- commenting this out "fixes" the problem
    // Otherwise the error is 
    // note: previous borrow of `cnt` occurs here; the mutable borrow prevents 
    // subsequent moves, borrows, or modification of `cnt` until the borrow ends

}

这里的错误是什么?我如何使这个“Iterator”成语在退出循环时以“Iterator”的结尾结束,而不是在它定义的块的末尾?另外,明确的生命周期T:'c是做什么的?

为了记录在案,我试图在使用上实现类似于str.chars()的Iterator。如果有更明智的方法,请告诉我。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-09-04 21:31:10

fn iter中,&'c mut selfself的可变借用与Counter的终身'c联系在一起。当你打电话给cnt.incr()时,你不能借用cnt,因为.cnt还活着(所以&'c mut self还在借用它)。

使代码工作的一种可能方法是将data移动到Counter中,而不是存储对它的借用引用,如下所示:

代码语言:javascript
复制
struct Counter <T> {
    val: u32,
    data: T
}

如果希望将数据保留为引用,另一种选择是在CounterIterator结构中引入第二个命名生存期,以便可向Counter借入的可变值可以比Counter本身活得更短。

代码语言:javascript
复制
// we now have a shorter lifetime ('s) and a longer one ('l). This is 
// expressed to the compiler by the 'l: 's bound that says "'l lives 
// at least as long as 's"
struct CounterIterator<'s, 'l: 's, T: 'l> {
    iter: &'s mut Counter<'l, T>,
    num: u32
}

impl<'c,  T> Counter <'c, T> {
// ...
    // now the &mut self can live as long as CounterIterator, not necessarily as
    // long as Counter. This allows it to be released as soon as the iteration
    // is over and CounterIterator goes out of scope
    fn iter<'a>(&'a mut self, num: u32) -> CounterIterator<'a,'c, T> {
        CounterIterator {
            iter: self,
            num: num
        }
    }
}

作为参考,因为语言还在不断变化:

代码语言:javascript
复制
$ rustc -v
rustc 0.12.0-pre-nightly (2e3858179 2014-09-03 00:51:00 +0000)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25654692

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档