当前位置:首页 > 科技  > 软件

一篇学会 Rust 内存布局

来源: 责编: 时间:2023-11-28 09:33:05 144观看
导读图片题图忘了来自哪里..整型,浮点型,struct,vec!,enum本文是对 Rust内存布局[1] 的学习与记录struct A { a: i64, b: u64,}struct B { a: i32, b: u64,}struct C { a: i64, b: u64, c: i32,}str

AJr28资讯网——每日最新资讯28at.com

图片图片AJr28资讯网——每日最新资讯28at.com

题图忘了来自哪里..AJr28资讯网——每日最新资讯28at.com

AJr28资讯网——每日最新资讯28at.com

整型,浮点型,struct,vec!,enum

AJr28资讯网——每日最新资讯28at.com

本文是对 Rust内存布局[1] 的学习与记录AJr28资讯网——每日最新资讯28at.com

AJr28资讯网——每日最新资讯28at.com

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>());}

输出AJr28资讯网——每日最新资讯28at.com

i32类型占的内存空间为:4字节i64类型占的内存空间为:8字节[i64;4]占的内存空间为:32字节结构体A占的内存空间为:16字节结构体B占的内存空间为:16字节结构体C占的内存空间为:24字节结构体D占的内存空间为:24字节

没啥好说的,和Go一样,struct会存在内存对齐/内存填充(8字节对齐)AJr28资讯网——每日最新资讯28at.com

D是因为编译器会优化内存布局,字段顺序重排AJr28资讯网——每日最新资讯28at.com

AJr28资讯网——每日最新资讯28at.com

AJr28资讯网——每日最新资讯28at.com

Rust中的Vec!和Go中的slice差不多,都是占24Byte,三个字段AJr28资讯网——每日最新资讯28at.com

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类型,AJr28资讯网——每日最新资讯28at.com

会有一个tag字段,uint64,来标记变体,是None值还是Some值AJr28资讯网——每日最新资讯28at.com

struct Option {    uint64 tag; // 占8字节 Some None    i64; //实际存放的数据}

AJr28资讯网——每日最新资讯28at.com

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>()    );}

输出为:AJr28资讯网——每日最新资讯28at.com

Data这个Enum类型占的内存空间为:32字节AJr28资讯网——每日最新资讯28at.com

AJr28资讯网——每日最新资讯28at.com

Rust的enum类似C++ std::variant的实现(大致是用union实现的)AJr28资讯网——每日最新资讯28at.com

union的内存大小是其成员中最大的那个成员的大小,AJr28资讯网——每日最新资讯28at.com

类似的,对于Data这个Enum类型,会选择最大的那个成员的大小AJr28资讯网——每日最新资讯28at.com

所以24+tag的8字节,最终为32字节 (tag在这里就用来标识其为i32,还是f64,或者是Vec)AJr28资讯网——每日最新资讯28at.com

AJr28资讯网——每日最新资讯28at.com

嵌套的枚举:AJr28资讯网——每日最新资讯28at.com

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>()    );}

输出:AJr28资讯网——每日最新资讯28at.com

OptData这个Option类型占的内存空间为:32字节AJr28资讯网——每日最新资讯28at.com

因为编译器会对嵌套的枚举类型进行优化,会将其tag展开, 把多个tag合在一起了,类似下面:AJr28资讯网——每日最新资讯28at.com

展开变成一个枚举(None是uint64,能标识非常多信息)AJr28资讯网——每日最新资讯28at.com

type OptData = Option<Data>;enum Option {    Some,    None,}enum OptData_ {    I32(i32);    F64(f64);    Bytes(SimpleVec<u8>),    None}

AJr28资讯网——每日最新资讯28at.com

元组tuple

AJr28资讯网——每日最新资讯28at.com

rust中的元组大小固定吗?AJr28资讯网——每日最新资讯28at.com

在Rust中,元组的大小是固定的。这里解释一下元组大小固定的含义:AJr28资讯网——每日最新资讯28at.com

  • 元组中的元素类型和数量在编译期就已经确定,不能在运行期修改。
  • 编译器会根据元组中元素的类型,预先分配足够的内存用于存储这些元素。
  • 元组的内存布局和大小也在编译期就确定下来了,运行期不会改变。
  • 尝试创建包含不同类型或数量元素的元组,是编译时错误。

举个例子:AJr28资讯网——每日最新资讯28at.com

let tuple = (1, 2.0, "three");

这里元组包含一个i32,一个f64和一个字符串。编译器会预先知道:AJr28资讯网——每日最新资讯28at.com

  • 元组元素类型为i32, f64, &str
  • i32占用4字节,f64占用8字节,&str占据一个指针的空间
  • 所以该元组占用的内存大小为4 + 8 + 8 = 20字节

这20字节的内存在编译时就已分配,运行期不会改变。AJr28资讯网——每日最新资讯28at.com

如果后续试图给这个元组添加或减少元素,编译都会报错。AJr28资讯网——每日最新资讯28at.com

所以说,元组的大小和内容是固定的,这是Rust实现方式的一部分。AJr28资讯网——每日最新资讯28at.com

AJr28资讯网——每日最新资讯28at.com

AJr28资讯网——每日最新资讯28at.com

更多可参考Rust 数据内存布局[2]AJr28资讯网——每日最新资讯28at.com

参考资料

[1]Rust内存布局: https://www.bilibili.com/video/BV1Bm4y1c71rAJr28资讯网——每日最新资讯28at.com

[2]Rust 数据内存布局: https://blog.csdn/techdashen/article/details/120257323AJr28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-34571-0.html一篇学会 Rust 内存布局

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Python爬虫神器:Beautiful Soup指南,轻松解析网页数据!

下一篇: 事务管理 vs. 锁控制:你真的分得清吗?

标签:
  • 热门焦点
Top