2015-12-21 35 views
4

我擁有一個數組(固定大小= 3)的所有權,並且我想對它進行迭代,並隨時移動元素。基本上,我想爲固定大小的陣列實施IntoIterator將對象移出陣列

由於數組沒有在標準庫中實現這個特徵(我理解爲什麼),是否有解決方法來獲得所需的效果?我的物品不是Copy也不是Clone。我可以在陣列中創建一個Vec,然後迭代到Vec,但我甚至不知道該怎麼做。

(有關信息,我想履行的Complete陣列)

這裏是的情況一個簡單的例子(與幼稚iter()嘗試):http://is.gd/fxN7Yw

// No-copy, No-clone struct 
#[derive(Debug)] 
struct Foo; 

// A method that needs an owned Foo 
fn bar(foo: Foo) { println!("{:?}", foo); } 

fn main() { 
    let v: [Foo; 3] = [Foo,Foo,Foo]; 

    for a in v.iter() { 
     bar(*a); 
    } 
} 

給出

<anon>:13:13: 13:15 error: cannot move out of borrowed content [E0507] 
<anon>:13   bar(*a); 
         ^~ 
error: aborting due to previous error 

回答

7

你需要的核心東西是mem::replacemem::uninitialized

let one = unsafe { mem::replace(&mut v[0], mem::uninitialized()) }; 
bar(one); 

這會用一個未初始化的值替換一個實際值,從而使您回到實際值。這只是一個簡單的問題,你可以做幾次,而且你很好。

只有一個小問題:你看到unsafe?你猜到了;在更廣泛的情況下,這是完全可怕的!

我們正在離開那個充滿任意位的數組。在這個的情況下,當該數組超出範圍時沒有什麼特別的事情發生,因爲該類型沒有特殊的Drop實現。但如果有的話,它會訪問無效的內存。壞消息!除此之外,沒有什麼能夠阻止我們嘗試訪問數組中的無效值!

真的你要做的是track數組中有多少個值是有效/無效的。當數組被刪除時,您可以刪除有效的項目並忽略無效項目。此外,這將會是非常好的,如果我們能夠使這項工作對不同大小的陣列...

這也正是arrayvec用武之地。它不會做完全相同相同的代碼,但它同樣語義:

extern crate arrayvec; 

use arrayvec::ArrayVec; 

#[derive(Debug)] 
struct Foo; 

fn bar(foo: Foo) { println!("{:?}", foo) } 

fn main() { 
    let v = ArrayVec::from([Foo, Foo, Foo]); 

    for f in v { 
     bar(f); 
    } 
} 
+0

謝謝。所以沒有安全的方法可以單獨使用'Array',但是使用'ArrayVec'可能會影響它與'Vec'之間的折衷。 – Gyscos

6

您可以使用Option<Foo>代替陣列的Foo的陣列。它當然有一些記憶懲罰。函數take()None替換數組中的值。

#[derive(Debug)] 
struct Foo; 

// A method that needs an owned Foo 
fn bar(foo: Foo) { println!("{:?}", foo); } 

fn main() { 
    let mut v = [Some(Foo),Some(Foo),Some(Foo)]; 

    for a in &mut v { 
     a.take().map(|x| bar(x)); 
    } 
} 
+0

和'Option :: take' [正在執行](https://github.com/rust-lang/rust/blob/1.5.0/src/libcore/option.rs#L689-L691)與'mem ::替換'^ _ ^。 'Option'具有一個始終可以創建的值,並且適用於「虛擬」或「無操作」值(「無」)。 – Shepmaster

+0

@shepmaster區別在於項目中缺少不安全的代碼。 –

+0

@ MahmoudAl-Qudsi我不知道我跟着你。**所有**解決方案(這一個和我的答案中的兩個)使用不安全的代碼,唯一的區別是它在哪裏。這個在標準庫中。我的箱子裏有一個,一個在箱子裏。 – Shepmaster