-
Option<T>
類型在Rust中使用了空指針優(yōu)化(null pointer optimization)來保證該類型在編譯后的二進(jìn)制文件中占用0個(gè)字節(jié)。None
變量是通過一個(gè)空指針null pointer
來表示; - 內(nèi)存地址、指針、引用的區(qū)別,內(nèi)存地址是指在內(nèi)存中的一個(gè)字節(jié),由匯編語(yǔ)言提供的一個(gè)抽象;指針,有時(shí)候也稱為裸指針(raw pointer),是指向某種數(shù)據(jù)類型的內(nèi)存地址,指針是由高級(jí)語(yǔ)言提供的抽象;引用,是一種指針,在動(dòng)態(tài)類型中,引用包含了一個(gè)指針以及一些額外的保證,引用是由Rust提供的抽象;
- Rust的引用提供了比指針更多的好處:引用永遠(yuǎn)指向有效的數(shù)據(jù);引用的字節(jié)排列是緊湊的,有助于CPU快速讀取;引用能夠提供變長(zhǎng)數(shù)據(jù)類型的長(zhǎng)度保證,引用的結(jié)構(gòu)中除了內(nèi)部指針本身外,還提供一個(gè)數(shù)據(jù)長(zhǎng)度的變量,確保程序永遠(yuǎn)不會(huì)跑到內(nèi)存范圍之外;
-
{:p}
可以把變量安裝指針的形式打印,打印其內(nèi)存地址; - 代碼列表6.3展示了兩種從u8數(shù)組轉(zhuǎn)化成字符串的形式,b變量通過
String::from_raw_parts(ptr, size, capa)
首先把[u8; 10]
轉(zhuǎn)化成*const u8
然后轉(zhuǎn)化成*mut u8
;c變量引入了CStr外部接口,通過CStr::from_ptr(c_ptr)
獲取一個(gè)以\0
結(jié)尾的C語(yǔ)言類型的字符串;b和c變量都需要把[u8, n]
先轉(zhuǎn)換成*const u8
在轉(zhuǎn)換成所需的相應(yīng)指針類型; - Rust的裸指針分為
*const T
和*mut T
,分別是不可變裸指針和可變裸指針,兩者之間可以自由轉(zhuǎn)換,Rust的引用&mut T and &T
編譯出來的結(jié)果就成了裸指針,也就是在實(shí)際運(yùn)行過程中不需要通過unsafe也能得到裸指針的性能; - 使用裸指針的原因:不可避免的使用,當(dāng)需要系統(tǒng)調(diào)用OS功能或者某些第三方代碼需要裸指針,一般是對(duì)C寫的一些程序的外部調(diào)用;需要多個(gè)地方同時(shí)訪問數(shù)據(jù)并且對(duì)運(yùn)行時(shí)性能要求極高的時(shí)候;
- C++中的智能指針在Rust中對(duì)應(yīng)的是
core::ptr::{Unique, Shared, Weak}
,胖指針(fat pointer)通常指內(nèi)存布局,對(duì)比瘦指針(thin pointer,通常也指裸指針,只有一個(gè)usize寬度),要更大一些,通常有2個(gè)usize寬度甚至更多; -
core::ptr::Unique
是rust中String, Box<T>
的構(gòu)成要素;core::ptr::Shared
是Rc<T>, Arc<T>
的構(gòu)成要素,如果要實(shí)現(xiàn)自己的智能指針,可以參考這些智能指針的實(shí)現(xiàn)細(xì)節(jié); -
std::rc::Weak, std::arc::Weak
可用于內(nèi)部互相指向的數(shù)據(jù)結(jié)構(gòu),避免循環(huán)指針的問題;alloc::raw_vec::RawVec
用于實(shí)現(xiàn)了Vec<T>, VecDeq<T>
,它能夠很聰明地給任何類型的數(shù)據(jù)分配和回收內(nèi)存;std::cell::UnsafeCell
用于實(shí)現(xiàn)Cell<T>, RefCell<T>
,來提供內(nèi)部可變性(interior mutability); - "When in doubt, prefer the stack"表示了當(dāng)不知道把數(shù)據(jù)放在堆上還是棧上時(shí),優(yōu)先放在棧上,因?yàn)闂1容^快,這句話的Rust版本是,
When in doulbe, use types that implement Sized
,即實(shí)現(xiàn)了Sized特征的類型會(huì)優(yōu)先放在棧上存儲(chǔ); - 如何讓一個(gè)函數(shù)同時(shí)接受
&str, String
兩種類型的參數(shù),可以使用參數(shù)模板<T: AsRef<str>>
表示參數(shù)T可以稱為str的引用,從而調(diào)用.as_ref().len()
方法,詳細(xì)可見Page189; - 表6.1給出了簡(jiǎn)單的棧和堆的對(duì)比,注意表中說明了在沒有Unsafe的Rust中,使用堆是安全的;
- 幾個(gè)通用的優(yōu)化堆內(nèi)存分配的方法:提前分配好足夠的空間,將其初始化為0,到使用的時(shí)候再將其改為非0值,這種方法比較危險(xiǎn),可能會(huì)引發(fā)Rust的生命周期檢查;自己針對(duì)程序設(shè)計(jì)一個(gè)allocator,能更有效地分配出所需的空間;調(diào)研使用
arena::{Arena, TypedArena}
,允許對(duì)象邊創(chuàng)建邊使用(created on the fly),arena是一個(gè)第三方庫(kù),鏈接; - 虛擬內(nèi)存常用術(shù)語(yǔ),頁(yè)(Page)、字(Word)、頁(yè)錯(cuò)誤(Page fault)、交換(Swapping)、虛擬內(nèi)存(Virtual memory)、實(shí)際內(nèi)存(Real memory)、頁(yè)表(Page table)、段(Segment)、段錯(cuò)誤(Segmentation fault)、MMU、TLB(translation lookaside buffer),詳見Page203;
- 6.4.2節(jié)講了段錯(cuò)誤(segmentation fault),當(dāng)訪問一個(gè)非法區(qū)域時(shí)會(huì)產(chǎn)生,可以參考下代碼實(shí)現(xiàn);
- 6.4.3節(jié)講了MMU(memory mamagement unit)的作用,即把虛擬地址翻譯成物理地址,以及使用TLB緩存加速的作用, 206頁(yè)講了操作系統(tǒng)和CPU在翻譯地址過程中用到的一些小tricks;
- 下圖講了一個(gè)可執(zhí)行文件(ELF)是如何加載到虛擬內(nèi)存并運(yùn)行的過程
文章來源地址http://www.zghlxwxcb.cn/news/detail-481483.html
文章來源:http://www.zghlxwxcb.cn/news/detail-481483.html
到了這里,關(guān)于Rust in Action筆記 第六章 內(nèi)存的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!