我有以下示例代码:
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
有点例外,因为它的结构有一些保证。