Tenho duas estruturas T e K, e o tamanho de T é maior ou igual a K. Suponha o seguinte:
struct T {
k: K,
t_val: u32,
}
struct K {
k_val: u64,
}
Quero mapear Vec para Vec sem nenhuma nova alocação de heap. Isso deve ser possível de forma otimizada, já que o Vec mapeado definitivamente exigirá menos memória do que o Vec, pois T tem 12 bytes e K tem 8 bytes, e os tipos estão lá apenas para calcular o deslocamento. Aqui está como imagino que ficaria:
*ptr -> [12(T) | 12(T) | 12(T)]
|
iter_k
iter_t
*ptr -> [8(K) | 4(garbage) | 12(T) | 12(T)]
| |
iter_k iter_t
*ptr -> [8(K) | 8(K) | 8(garbage) | 12(T)]
| |
iter_k iter_t
*ptr -> [8(K) | 8(K) | 8(K) | 12(garbage)]
| |
iter_k iter_t
E os últimos 12 bytes de lixo são irrelevantes, pois o tamanho é 3 e pode permanecer como capacidade extra para o novo Vec.
O código para fazer isso é surpreendentemente simples:
Sim, é isso. Se você olhar em godbolt , verá que isso não aloca.
Claro, há *mágica* envolvida. A biblioteca padrão Rust fornece especialização para iteradores
Vec
-to-Vec
que não alocam sempre que possível. Claro, isso não é garantido .Você pode garantir isso usando um código inseguro, mas não deveria ter motivos para isso.
Observe que isso só é possível quando o alinhamento de
K
é o mesmo que o alinhamento paraT
, e o tamanho é uma multiplicação, porque ele precisa corresponder para desalocação.