自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇學會 Rust 內(nèi)存布局

開發(fā) 前端
union的內(nèi)存大小是其成員中最大的那個成員的大小,類似的,對于Data這個Enum類型,會選擇最大的那個成員的大小所以24+tag的8字節(jié),最終為32字節(jié) (tag在這里就用來標識其為i32,還是f64,或者是Vec)。

圖片圖片

題圖忘了來自哪里..

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

本文是對 Rust內(nèi)存布局[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類型占的內(nèi)存空間為:{}字節(jié)", std::mem::size_of::<i32>());
    println!("i64類型占的內(nèi)存空間為:{}字節(jié)", std::mem::size_of::<i64>());
    println!(
        "[i64;4]占的內(nèi)存空間為:{}字節(jié)",
        std::mem::size_of::<[i64; 4]>()
    );

    println!("結(jié)構(gòu)體A占的內(nèi)存空間為:{}字節(jié)", std::mem::size_of::<A>());
    println!("結(jié)構(gòu)體B占的內(nèi)存空間為:{}字節(jié)", std::mem::size_of::<B>());
    println!("結(jié)構(gòu)體C占的內(nèi)存空間為:{}字節(jié)", std::mem::size_of::<C>());
    println!("結(jié)構(gòu)體D占的內(nèi)存空間為:{}字節(jié)", std::mem::size_of::<D>());
}

輸出

i32類型占的內(nèi)存空間為:4字節(jié)
i64類型占的內(nèi)存空間為:8字節(jié)
[i64;4]占的內(nèi)存空間為:32字節(jié)
結(jié)構(gòu)體A占的內(nèi)存空間為:16字節(jié)
結(jié)構(gòu)體B占的內(nèi)存空間為:16字節(jié)
結(jié)構(gòu)體C占的內(nèi)存空間為:24字節(jié)
結(jié)構(gòu)體D占的內(nèi)存空間為:24字節(jié)

沒啥好說的,和Go一樣,struct會存在內(nèi)存對齊/內(nèi)存填充(8字節(jié)對齊)

D是因為編譯器會優(yōu)化內(nèi)存布局,字段順序重排

Rust中的Vec!和Go中的slice差不多,都是占24Byte,三個字段

struct SimpleVec<T> {
    len: usize,      // 8
    capacity: usize, //8
    data: *mut T,    //8
}

fn main() {
    println!(
        "Vec!類型占的內(nèi)存空間為:{}字節(jié)",
        std::mem::size_of::<SimpleVec<i32>>()
    );

    println!(
        "Option<i64>類型占的內(nèi)存空間為:{}字節(jié)",
        std::mem::size_of::<Option<i64>>()
    );
}
Vec!類型占的內(nèi)存空間為:24字節(jié)
Option<i64>類型占的內(nèi)存空間為:16字節(jié)

但是對于enum類型,

會有一個tag字段,uint64,來標記變體,是None值還是Some值

struct Option {
    uint64 tag; // 占8字節(jié) Some None
    i64; //實際存放的數(shù)據(jù)
}

struct SimpleVec<T> {
    len: usize,      // 8
    capacity: usize, //8
    data: *mut T,    //8
}

enum Data {
    // tag,uint64,8字節(jié)
    I32(i32),             //  4字節(jié),但需內(nèi)存對齊到8字節(jié)?
    F64(f64),             // 8字節(jié)
    Bytes(SimpleVec<u8>), // 24字節(jié)
}

fn main() {
    println!(
        "Data這個Enum類型占的內(nèi)存空間為:{}字節(jié)",
        std::mem::size_of::<Data>()
    );
}

輸出為:

Data這個Enum類型占的內(nèi)存空間為:32字節(jié)

Rust的enum類似C++ std::variant的實現(xiàn)(大致是用union實現(xiàn)的)

union的內(nèi)存大小是其成員中最大的那個成員的大小,

類似的,對于Data這個Enum類型,會選擇最大的那個成員的大小

所以24+tag的8字節(jié),最終為32字節(jié) (tag在這里就用來標識其為i32,還是f64,或者是Vec)

嵌套的枚舉:

struct SimpleVec<T> {
    len: usize,      // 8
    capacity: usize, //8
    data: *mut T,    //8
}

enum Data {
    // tag,uint64,8字節(jié)
    I32(i32),             //  4字節(jié),但需內(nèi)存對齊到8字節(jié)?
    F64(f64),             // 8字節(jié)
    Bytes(SimpleVec<u8>), // 24字節(jié)
}

type OptData = Option<Data>;

fn main() {
    println!(
        "OptData這個Option類型占的內(nèi)存空間為:{}字節(jié)",
        std::mem::size_of::<OptData>()
    );
}

輸出:

OptData這個Option類型占的內(nèi)存空間為:32字節(jié)

因為編譯器會對嵌套的枚舉類型進行優(yōu)化,會將其tag展開, 把多個tag合在一起了,類似下面:

展開變成一個枚舉(None是uint64,能標識非常多信息)

type OptData = Option<Data>;

enum Option {
    Some,
    None,
}

enum OptData_ {
    I32(i32);
    F64(f64);
    Bytes(SimpleVec<u8>),
    None
}

元組tuple

rust中的元組大小固定嗎?

在Rust中,元組的大小是固定的。這里解釋一下元組大小固定的含義:

  • 元組中的元素類型和數(shù)量在編譯期就已經(jīng)確定,不能在運行期修改。
  • 編譯器會根據(jù)元組中元素的類型,預先分配足夠的內(nèi)存用于存儲這些元素。
  • 元組的內(nèi)存布局和大小也在編譯期就確定下來了,運行期不會改變。
  • 嘗試創(chuàng)建包含不同類型或數(shù)量元素的元組,是編譯時錯誤。

舉個例子:

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

這里元組包含一個i32,一個f64和一個字符串。編譯器會預先知道:

  • 元組元素類型為i32, f64, &str
  • i32占用4字節(jié),f64占用8字節(jié),&str占據(jù)一個指針的空間
  • 所以該元組占用的內(nèi)存大小為4 + 8 + 8 = 20字節(jié)

這20字節(jié)的內(nèi)存在編譯時就已分配,運行期不會改變。

如果后續(xù)試圖給這個元組添加或減少元素,編譯都會報錯。

所以說,元組的大小和內(nèi)容是固定的,這是Rust實現(xiàn)方式的一部分。

更多可參考Rust 數(shù)據(jù)內(nèi)存布局[2]

參考資料

[1]Rust內(nèi)存布局: https://www.bilibili.com/video/BV1Bm4y1c71r

[2]Rust 數(shù)據(jù)內(nèi)存布局: https://blog.csdn.net/techdashen/article/details/120257323

責任編輯:武曉燕 來源: 旅途散記
相關推薦

2022-01-02 08:43:46

Python

2022-02-07 11:01:23

ZooKeeper

2021-10-18 10:54:48

.NET內(nèi)存管理

2023-01-03 08:31:54

Spring讀取器配置

2021-05-11 08:54:59

建造者模式設計

2021-07-05 22:11:38

MySQL體系架構(gòu)

2021-07-06 08:59:18

抽象工廠模式

2022-08-26 09:29:01

Kubernetes策略Master

2021-07-02 09:45:29

MySQL InnoDB數(shù)據(jù)

2022-08-23 08:00:59

磁盤性能網(wǎng)絡

2021-10-27 09:59:35

存儲

2021-07-02 08:51:29

源碼參數(shù)Thread

2021-07-16 22:43:10

Go并發(fā)Golang

2021-09-28 08:59:30

復原IP地址

2022-04-12 08:30:52

回調(diào)函數(shù)代碼調(diào)試

2022-10-20 07:39:26

2021-10-29 07:35:32

Linux 命令系統(tǒng)

2023-03-13 21:38:08

TCP數(shù)據(jù)IP地址

2023-11-01 09:07:01

Spring裝配源碼

2021-10-14 10:22:19

逃逸JVM性能
點贊
收藏

51CTO技術棧公眾號