2015-12-15 47 views
1

我試圖初始化None值的盒裝切片,使得底層類型T不需要實現CloneCopy。下面幾個的理想解決方案:初始化沒有克隆或複製的盒裝切片

fn by_vec<T>() -> Box<[Option<T>]> { 
    vec![None; 5].into_boxed_slice() 
} 

fn by_arr<T>() -> Box<[Option<T>]> { 
    Box::new([None; 5]) 
} 

不幸的是,by_vec實現需要T: Cloneby_arr需要實行T: Copy。我已經嘗試了幾個方法:

fn by_vec2<T>() -> Box<[Option<T>]> { 
    let v = &mut Vec::with_capacity(5); 
    for i in 0..v.len() { 
     v[i] = None; 
    } 
    v.into_boxed_slice() // Doesn't work: cannot move out of borrowed content 
} 

fn by_iter<T>() -> Box<[Option<T>]> { 
    (0..5).map(|_| None).collect::<Vec<Option<T>>>().into_boxed_slice() 
} 

by_vec2不會讓過去的編譯器(我不知道我明白爲什麼),但by_iter一樣。我擔心collect的性能 - 它是否需要調整它在迭代時收集的矢量的大小,還是可以分配正確大小的矢量以開始?

也許我正在談論這一切都是錯誤的 - 我對Rust很新,所以任何提示將不勝感激!

回答

4

讓我們從by_vec2開始。您正在參照Vec參考&mut。您不應該這樣做,直接與Vec工作,並使v綁定可變。

然後,您將遍歷容量爲5,長度爲0的Vec的長度。這意味着您的循環永遠不會執行。你想要的是迭代0..v.cap()

由於您的v仍爲長度0,因此在循環中訪問v[i]將在運行時出現混亂。你真正想要的是v.push(None)。這通常會導致重新分配,但在你的情況下,你已經分配了Vec::with_capacity,所以推送5次不會分配。

這次我們沒有參考Vec所以into_boxed_slice實際上會工作。

fn by_vec2<T>() -> Box<[Option<T>]> { 
    let mut v = Vec::with_capacity(5); 
    for _ in 0..v.capacity() { 
     v.push(None); 
    } 
    v.into_boxed_slice() 
} 

您的by_iter函數實際上只分配一次。由0..5創建的Range迭代器知道它恰好是5個元素長。因此collect實際上將檢查該長度並僅分配一次。

+2

我認爲這裏最重要的是* Range迭代器[...]知道它恰好是5個元素*。這就是我編寫這段代碼的方法,雖然我會在'collect'類型參數上使用類型推斷:'(0..5).map(| _ | None).collect :: >()。into_boxed_slice( )'。 – Shepmaster