图片
题图忘了来自哪里..
本文是对 Rust内存布局[1] 的学习与记录
struct A { a: i64, b: u64,}struct B { a: i32, b: u64,}struct C { a: i64, b: u64, c: i32,}struct D { a: i32, b: u64, c: i32, d: u64,}fn main() { println!("i32类型占的内存空间为:{}字节", std::mem::size_of::<i32>()); println!("i64类型占的内存空间为:{}字节", std::mem::size_of::<i64>()); println!( "[i64;4]占的内存空间为:{}字节", std::mem::size_of::<[i64; 4]>() ); println!("结构体A占的内存空间为:{}字节", std::mem::size_of::<A>()); println!("结构体B占的内存空间为:{}字节", std::mem::size_of::<B>()); println!("结构体C占的内存空间为:{}字节", std::mem::size_of::<C>()); println!("结构体D占的内存空间为:{}字节", std::mem::size_of::<D>());}
输出
i32类型占的内存空间为:4字节i64类型占的内存空间为:8字节[i64;4]占的内存空间为:32字节结构体A占的内存空间为:16字节结构体B占的内存空间为:16字节结构体C占的内存空间为:24字节结构体D占的内存空间为:24字节
没啥好说的,和Go一样,struct会存在内存对齐/内存填充(8字节对齐)
D是因为编译器会优化内存布局,字段顺序重排
Rust中的Vec!和Go中的slice差不多,都是占24Byte,三个字段
struct SimpleVec<T> { len: usize, // 8 capacity: usize, //8 data: *mut T, //8}fn main() { println!( "Vec!类型占的内存空间为:{}字节", std::mem::size_of::<SimpleVec<i32>>() ); println!( "Option<i64>类型占的内存空间为:{}字节", std::mem::size_of::<Option<i64>>() );}
Vec!类型占的内存空间为:24字节Option<i64>类型占的内存空间为:16字节
但是对于enum类型,
会有一个tag字段,uint64,来标记变体,是None值还是Some值
struct Option { uint64 tag; // 占8字节 Some None i64; //实际存放的数据}
struct SimpleVec<T> { len: usize, // 8 capacity: usize, //8 data: *mut T, //8}enum Data { // tag,uint64,8字节 I32(i32), // 4字节,但需内存对齐到8字节? F64(f64), // 8字节 Bytes(SimpleVec<u8>), // 24字节}fn main() { println!( "Data这个Enum类型占的内存空间为:{}字节", std::mem::size_of::<Data>() );}
输出为:
Data这个Enum类型占的内存空间为:32字节
Rust的enum类似C++ std::variant的实现(大致是用union实现的)
union的内存大小是其成员中最大的那个成员的大小,
类似的,对于Data这个Enum类型,会选择最大的那个成员的大小
所以24+tag的8字节,最终为32字节 (tag在这里就用来标识其为i32,还是f64,或者是Vec)
嵌套的枚举:
struct SimpleVec<T> { len: usize, // 8 capacity: usize, //8 data: *mut T, //8}enum Data { // tag,uint64,8字节 I32(i32), // 4字节,但需内存对齐到8字节? F64(f64), // 8字节 Bytes(SimpleVec<u8>), // 24字节}type OptData = Option<Data>;fn main() { println!( "OptData这个Option类型占的内存空间为:{}字节", std::mem::size_of::<OptData>() );}
输出:
OptData这个Option类型占的内存空间为:32字节
因为编译器会对嵌套的枚举类型进行优化,会将其tag展开, 把多个tag合在一起了,类似下面:
展开变成一个枚举(None是uint64,能标识非常多信息)
type OptData = Option<Data>;enum Option { Some, None,}enum OptData_ { I32(i32); F64(f64); Bytes(SimpleVec<u8>), None}
rust中的元组大小固定吗?
在Rust中,元组的大小是固定的。这里解释一下元组大小固定的含义:
举个例子:
let tuple = (1, 2.0, "three");
这里元组包含一个i32,一个f64和一个字符串。编译器会预先知道:
这20字节的内存在编译时就已分配,运行期不会改变。
如果后续试图给这个元组添加或减少元素,编译都会报错。
所以说,元组的大小和内容是固定的,这是Rust实现方式的一部分。
更多可参考Rust 数据内存布局[2]
[1]Rust内存布局: https://www.bilibili.com/video/BV1Bm4y1c71r
[2]Rust 数据内存布局: https://blog.csdn/techdashen/article/details/120257323
本文链接:http://www.28at.com/showinfo-26-34571-0.html一篇学会 Rust 内存布局
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com