我一直在撞墙,试图弄清楚如何管理同一个较大切片的多个切片。我这样做的主要动机是我开始使用一些大切片,并逐渐使用越来越小的子切片,直到子切片只包含一个元素。
从高层次的角度来看,我不明白为什么不能这样做,因为我不需要移动或改变原始切片。我只需要切片的多个视图,其生命周期与原始切片相同。
为了说明,请参考此图:
原始切片为绿色,每个层向下表示尺寸越来越小的切片,直到切片中只有一个元素。我想要的是确保每个切片的元素的生命周期“到达”到原始切片,而不是取决于它上面的切片的寿命。我在while循环中使用这些切片,并将每个切片存储在一个持续循环持续时间的队列中。
我遇到的问题是切片不能“活得足够长”,但我不太明白为什么会这样。
由于每个切片仅引用原始切片,是否可以将这些切片存储为队列中的“拥有切片”而不是新的向量?性能上是否有差异?将片段边界的索引存储在队列中以供以后使用会更好吗?感谢所有的帮助,谢谢。
以下是一些准确演示此问题的代码:
pub struct Split<'a> {
pub first_half: &'a [&'a [u8]],
pub second_half: &'a [&'a [u8]],
}
impl<'a> Split<'a> {
pub fn new(first_half: &'a [&'a [u8]], second_half: &'a [&'a [u8]]) -> Split<'a> {
Self {
first_half,
second_half,
}
}
}
fn make_smaller_slice<'a>(slice: &'a [&'a [u8]]) -> Vec<&'a [u8]> {
let mut smaller_slice = Vec::with_capacity(slice.len());
for elem in slice {
if true {
smaller_slice.push(*elem)
}
}
smaller_slice
}
fn main() {
let mut original_data = Vec::with_capacity(100);
for i in 0..100 {
original_data.push(vec![i]);
}
let original_slice = original_data
.iter()
.map(|x| x.as_slice())
.collect::<Vec<_>>();
let mut split_queue = vec![];
split_queue.push(Split::new(&original_slice[0..50], &original_slice[50..100]));
loop {
let split = split_queue.remove(0);
let first_half = split.first_half.split_at(split.first_half.len() / 2);
let processed_first_half_0 = make_smaller_slice(&first_half.0);
let processed_first_half_1 = make_smaller_slice(&first_half.1);
let first_split = Split::new(&processed_first_half_0, &processed_first_half_1);
split_queue.insert(0, first_split);
}
}
由此产生的错误:
error[E0597]: `processed_first_half_0` does not live long enough
--> src/main.rs:44:38
|
38 | let split = split_queue.remove(0);
| ----------- borrow used here, in later iteration of loop
...
44 | let first_split = Split::new(&processed_first_half_0, &processed_first_half_1);
| ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
45 | split_queue.insert(0, first_split);
46 | }
| - `processed_first_half_0` dropped here while still borrowed
error[E0597]: `processed_first_half_1` does not live long enough
--> src/main.rs:44:63
|
38 | let split = split_queue.remove(0);
| ----------- borrow used here, in later iteration of loop
...
44 | let first_split = Split::new(&processed_first_half_0, &processed_first_half_1);
| ^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
45 | split_queue.insert(0, first_split);
46 | }
| - `processed_first_half_1` dropped here while still borrowed
修改make_smaller_slice
以返回对切片而不是向量的引用可以解决问题。
pub struct Split<'a> {
pub first_half: &'a [&'a [u8]],
pub second_half: &'a [&'a [u8]]
}
impl<'a> Split<'a> {
pub fn new(first_half: &'a [&'a [u8]], second_half: &'a [&'a [u8]]) -> Split<'a> {
Self {
first_half,
second_half
}
}
}
fn make_smaller_slice<'a>(slice: &'a [&'a [u8]]) -> &'a[&'a [u8]] {
let mut start_bound = 0;
for i in 0..slice.len() {
if true {
start_bound = i;
}
}
&slice[start_bound..]
}
fn main() {
let mut original_data = Vec::with_capacity(100);
for i in 0..100 {
original_data.push(vec![i]);
}
let original_slice = original_data.iter().map(|x| x.as_slice()).collect::<Vec<_>>();
let mut split_queue = vec![];
split_queue.push(Split::new(&original_slice[0..50], &original_slice[50..100]));
loop {
let split = split_queue.remove(0);
let first_half = split.first_half.split_at(split.first_half.len() / 2);
let processed_first_half_0 = make_smaller_slice(&first_half.0);
let processed_first_half_1 = make_smaller_slice(&first_half.1);
let first_split = Split::new(&processed_first_half_0, &processed_first_half_1);
split_queue.insert(0, first_split);
}
}
感谢来自Reddit的_TheDust_。
您的代码中可能存在问题。在这两行中:
let split = split_queue.remove(0);
split_queue.insert(0, first_split);
这与split_queue
的长度成正比。你可能想用Vec
及其恒定时间方法VecDeque
和pop_front
替换push_front
。