Rust中向量迭代器、向量链和向量扁平化的内存大小(以字节为单位)



我有以下示例代码:

let vector_1 = vec![1, 2, 3];
let vector_2 = vec![4, 5, 6];
{ 
let vector_1_iter = vector_1.iter(); 
}
{ 
let chained = vector_1.iter().chain(vector_2.iter());
}
{
let vector_combined = vec![vector_1, vector_2];
let flatten = vector_combined.iter().flatten();
}

我想知道vector_1_iter、链式、扁平化的大小(以字节为单位(。如果我要找到vector_1和vector_2的大小,我只需要取向量的长度,并将其乘以i32的字节。然而,我不确定在将向量转换为迭代器之后,大小是否会改变。与链接和扁平化相同,它们占用的大小不等于数组的整个长度乘以每个数据类型的大小吗?

维奇的尺寸

Vec是一个结构体,由指向堆上分配的内存区域的指针、容量(显示可存储在堆内存中的项目总数(和长度(显示当前存储在堆存储器中的项目数(组成。

每一个都属于usize类型,在x8_64体系结构上占用8个字节。

因此,Vec<i32>占用的总内存实际上是24字节+(容量x4(。或者,更普遍地说:

std::mem::size_of::<Vec<T>>() + vector_1.capacity() * std::mem::size_of::<T>()

迭代器的大小

注意:

let vector_1_iter = vector_1.iter(); 

实际上并没有将vector_1转换为迭代器-iter借用向量,并返回一个引用它的std::slice::Iter。它没有任何额外的堆分配,我们可以看到它的内存大小如下:

println!("size of vector_1_iter {}", std::mem::size_of::<std::slice::Iter<'_, i32>>());

在我的机器上,结果是16个字节。

链式迭代器的大小

当我们使用chain将两个迭代器链接在一起时,两个迭代器都会被消耗,并返回一个std::iter::Chain。我们可以再次使用size_of,但当存在多个级别的泛型参数时,这开始变得有点难以表达。相反,我们可以使用std::mem::size_of_val:

let chained = vector_1.iter().chain(vector_2.iter());
println!("size of chained iter {}", std::mem::size_of_val(&chained));

在我的机器上,它打印32——这是有意义的,因为它包含了两个原始迭代器(每个迭代器都是16字节(。

扁平迭代器

我们可以使用相同的方法:

let vector_combined = vec![vector_1, vector_2];
let flatten = vector_combined.iter().flatten();    
println!("size of flattened iter {}", std::mem::size_of_val(&flatten));

这为我打印48

Rust Playground


请注意,上面的迭代器都没有使用它们正在迭代的原始容器。如果使用了into_iter(),结果会大不相同,因为此方法会消耗Vec并返回一个IntoIter结构,因此它拥有包含Vec实际内容的堆内存。

还要注意,这些结构的内容和布局都是实现细节,所以不能真正依赖于这些大小是恒定的。Vec有点例外,因为它的结构有一些保证。

最新更新