我試圖將一些C++代碼移植到Rust。它從幾種切片(字符串引用,延遲評估的字符串引用,物理文件的一部分)組成一個虛擬(.mp4)文件,並根據結果提供HTTP請求。 (如果您好奇,請參閱Mp4File,它利用FileSlice
接口及其在http.h中的具體實現。)Vec <MyTrait>沒有N堆分配?
以下是問題所在:我希望儘可能少地需要堆分配。假設我有一些resource::Slice
的實現,我希望可以自己弄清楚。然後我想使該組成他們所有的一個:
pub trait Slice : Send + Sync {
/// Returns the length of the slice in bytes.
fn len(&self) -> u64;
/// Writes bytes indicated by `range` to `out.`
fn write_to(&self, range: &ByteRange,
out: &mut io::Write) -> io::Result<()>;
}
// (used below)
struct SliceInfo<'a> {
range: ByteRange,
slice: &'a Slice,
}
/// A `Slice` composed of other `Slice`s.
pub struct Slices<'a> {
len: u64,
slices: Vec<SliceInfo<'a>>,
}
impl<'a> Slices<'a> {
pub fn new() -> Slices<'a> { ... }
pub fn append(&mut self, slice: &'a resource::Slice) { ... }
}
impl<'a> Slice for Slices<'a> { ... }
,並用它們來追加很多很多片用盡可能少的堆分配成爲可能。簡化,像這樣:
struct ThingUsedWithinMp4Resource {
slice_a: resource::LazySlice,
slice_b: resource::LazySlice,
slice_c: resource::LazySlice,
slice_d: resource::FileSlice,
}
struct Mp4Resource {
slice_a: resource::StringSlice,
slice_b: resource::LazySlice,
slice_c: resource::StringSlice,
slice_d: resource::LazySlice,
things: Vec<ThingUsedWithinMp4Resource>,
slices: resource::Slices
}
impl Mp4Resource {
fn new() {
let mut f = Mp4Resource{slice_a: ...,
slice_b: ...,
slice_c: ...,
slices: resource::Slices::new()};
// ...fill `things` with hundreds of things...
slices.append(&f.slice_a);
for thing in f.things { slices.append(&thing.slice_a); }
slices.append(&f.slice_b);
for thing in f.things { slices.append(&thing.slice_b); }
slices.append(&f.slice_c);
for thing in f.things { slices.append(&thing.slice_c); }
slices.append(&f.slice_d);
for thing in f.things { slices.append(&thing.slice_d); }
f;
}
}
但這不起作用。附加行會導致錯誤「f.slice_ *活得不夠長」,「引用必須對在塊中定義的生命週期a有效」,「...」,但借用的值僅對塊後綴下面的語句「。我認爲這與關於自引用結構的this question類似。這基本上是這樣,更多的間接。顯然這是不可能的。
那我能做些什麼呢?
我想我會很樂意給所有權的resource::Slices
在append
,但我不能把在Vec<SliceInfo>
使用的SliceInfo
一個resource::Slice
因爲resource::Slice
是一個特點和特徵,是未分級。我可以改爲Box<resource::Slice>
,但這意味着每個片的單獨堆分配。我想避免這種情況。 (可以有上千個Mp4Resource切片。)
我想在做一個枚舉,喜歡的東西的:
enum BasicSlice {
String(StringSlice),
Lazy(LazySlice),
File(FileSlice)
};
和使用,在SliceInfo
。我想我可以做這個工作。但它絕對限制了我的resource::Slices
課程的效用。我希望允許它在我沒有預料到的情況下使用,最好不必每次都定義一個新的枚舉。
還有其他的選擇嗎?
如果結構中包含有限的生命週期項,則該結構的生命週期也有限。 – WiSaGaN
@WiSaGaN在結構體中包含一個有限生命週期的項目是什麼意思?我的第一個方法是包含一個只有結構體纔會存在的項目。但我認爲沒有辦法來表達這一生,因此自引用結構是不可能的。無論如何,我很高興找到另一種方式,正如我在問題中所說的那樣...... –
嗯,除非這不完全正確。至少在C++中,一個類的成員是按照相反的順序被構造的,然後我有一個後來的成員引用了一個早期的成員。這是一件安全的事情,如果有幫助,我會很樂意在兩個單獨的堆分配中完成它們。但似乎仍然需要通過一生... –