将 Vec<T> 映射到 Vec<K>,无需新的堆分配,其中 size(T) >= size(K)

问题描述 投票:0回答:1

我有两个结构体T和K,并且T的大小大于或等于K。假设如下:

struct T {
    k: K,
    t_val: u32,
}

struct K {
    k_val: u64,
}

我想将 Vec 映射到 Vec,而不需要任何新的堆分配。这应该是最佳可能的,因为映射的 Vec 肯定比 Vec 需要更少的内存,因为 T 是 12 字节,K 是 8 字节,并且类型只是用来计算偏移量。这是我想象的样子:

*ptr -> [12(K) | 12(K) | 12(K)]
        |
      iter_k
      iter_t

*ptr -> [8(T) | 4(garbage) | 12(K) | 12(K)]
              |            |
            iter_t       iter_k

*ptr -> [8(T) | 8(T) | 8(garbage) | 12(K)]
                     |            |
                   iter_t       iter_k

*ptr -> [8(T) | 8(T) | 8(T) | 12(garbage)]
                            |            |
                          iter_t       iter_k

最后 12 字节垃圾是无关紧要的,因为大小为 3,并且可以保留作为新 Vec 的额外容量。

rust vector
1个回答
0
投票

执行此操作的代码非常简单:

pub fn map(v: Vec<T>) -> Vec<K> {
    v.into_iter().map(|v| K { k_val: v.k.k_val }).collect()
}

是的,就是这样。如果你查看 godbolt,你会发现它没有分配。

当然,其中涉及*魔法*。 Rust 标准库为

Vec
-to-
Vec
迭代器提供了专门化,这些迭代器尽可能不进行分配。当然,这不是保证

您可以通过使用不安全的代码来保证这一点,但您确实没有理由这样做。

© www.soinside.com 2019 - 2024. All rights reserved.