gpt4 book ai didi

rust - Vec 没有 N 堆分配?

转载 作者:行者123 更新时间:2023-11-29 08:04:01 25 4
gpt4 key购买 nike

我正在尝试将一些 C++ 代码移植到 Rust。它从几种切片(字符串引用、惰性求值字符串引用、物理文件的一部分)组成一个虚拟 (.mp4) 文件,并根据结果提供 HTTP 请求。 (如果您好奇,请参阅 Mp4File,它利用了 FileSlice 接口(interface)及其在 http.h 中的具体实现。)

这就是问题所在:我希望要求尽可能少的堆分配。假设我有几个 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_* 生命周期不够长”,“引用必须在生命周期内有效,如在 ... 的 block 上定义的”,“...但借用的值仅对语句后的 block 后缀”。我认为这类似于 this question关于自引用结构。这基本上就是这样,有更多的间接性。显然这是不可能的。

那么我可以做什么呢?

我想我很乐意将所有权授予 resource::Slicesappend , 但我不能放 resource::SliceSliceInfo用于 Vec<SliceInfo>因为resource::Slice是一个特征,并且特征是未定大小的。我可以做 Box<resource::Slice>相反,但这意味着为每个切片分配单独的堆。我想避免这种情况。 (每个 Mp4Resource 可以有数千个切片。)

我正在考虑做一个枚举,比如:

enum BasicSlice {
String(StringSlice),
Lazy(LazySlice),
File(FileSlice)
};

并在 SliceInfo 中使用它.我想我可以完成这项工作。但它确实限制了我的 resource::Slices 的效用类(class)。我想让它在我没有预料到的情况下很容易使用,最好是不必每次都定义一个新的枚举。

还有其他选择吗?

最佳答案

您可以添加 User BasicSlice 的变体枚举,需要 Box<SliceInfo> .这样只有用户的特殊情况才会占用额外的分配,而正常路径得到优化。

关于rust - Vec<MyTrait> 没有 N 堆分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37267201/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com