簡體   English   中英

如何實現帶框值的迭代器?

[英]How to implement Iterator for boxed values?

我有一個結構,通過方法給出的數字next的特質Iterator

struct Numbers{
    number: usize,
    count: usize
}

impl Iterator for Numbers {
    type Item = usize;

    fn next(&mut self) -> Option<Self::Item> {
        if self.count > 0 {
            self.count -= 1;
            return Some(self.number);
        }

        return None;
    }
}

fn main(){
    let numbers = Numbers{
        number: 777,
        count: 10
    };

    for n in numbers {
        println!{"{:?}", n};
    }
}

使用usize類型可以正常工作。 但是具有Box類型的相同代碼會產生編譯錯誤:

struct Numbers{
    number: Box<usize>,
    count: usize
}

impl Iterator for Numbers {
    type Item = Box<usize>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.count > 0 {
            self.count -= 1;
            return Some(self.number);
        }

        return None;
    }
}

fn main(){
    let numbers = Numbers{
        number: Box::new(777),
        count: 10
    };

    for n in numbers {
        println!{"{:?}", n};
    }
}

./numbers.rs:12:25:12:29錯誤:無法移出借用的內容

./numbers.rs:12返回Some(self.number);

如何正確實現帶框值的迭代器?

這歸結於Rust的所有權模型以及復制和移動語義之間的區別。 Box<T>具有移動語義,未實現Copy ,因此return Some(self.number); 會移動self.number ,獲得它的所有權; 但這是不允許的,因為這將需要消耗self ,而self只能通過可變引用來獲取。

您有幾種選擇(在這里我寫“具有移動語義的對象”,在這種情況下,我的意思是self.number ):

  1. 不要使用移動語義返回對象,使用復制語義引用返回其他內容,例如使用引用而不是裝箱的值(返回引用將要求迭代器對象與要迭代的對象不同,以便您可以編寫Item的有效期;因此,不適用於您的特定用例)或未裝箱的編號。

  2. 構造一個新值以基於具有移動語義的對象返回:

     impl Iterator for Numbers { type Item = Box<usize>; fn next(&mut self) -> Option<Self::Item> { if self.count > 0 { self.count -= 1; Some(Box::new(self.number)) } else { None } } } 
  3. 使用移動語義克隆對象(實際上,這是第二種選擇的簡化形式):

     impl Iterator for Numbers { type Item = Box<usize>; fn next(&mut self) -> Option<Self::Item> { if self.count > 0 { self.count -= 1; Some(self.number.clone()) } else { None } } } 
  4. 構造一個新值,以移動語義代替對象:

     use std::mem; impl Iterator for Numbers { type Item = Box<usize>; fn next(&mut self) -> Option<Self::Item> { if self.count > 0 { self.count -= 1; let number = mem::replace(&mut self.number, Box::new(0)); // self.number now contains 0 Some(number) } else { None } } } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM