Option<T>
类型在Rust中使用了空指针优化(null pointer optimization)来保证该类型在编译后的二进制文件中占用0个字节。None
变量是通过一个空指针null pointer
来表示;- 内存地址、指针、引用的区别,内存地址是指在内存中的一个字节,由汇编语言提供的一个抽象;指针,有时候也称为裸指针(raw pointer),是指向某种数据类型的内存地址,指针是由高级语言提供的抽象;引用,是一种指针,在动态类型中,引用包含了一个指针以及一些额外的保证,引用是由Rust提供的抽象;
- Rust的引用提供了比指针更多的好处:引用永远指向有效的数据;引用的字节排列是紧凑的,有助于CPU快速读取;引用能够提供变长数据类型的长度保证,引用的结构中除了内部指针本身外,还提供一个数据长度的变量,确保程序永远不会跑到内存范围之外;
{:p}
可以把变量安装指针的形式打印,打印其内存地址;- 代码列表6.3展示了两种从u8数组转化成字符串的形式,b变量通过
String::from_raw_parts(ptr, size, capa)
首先把[u8; 10]
转化成*const u8
然后转化成*mut u8
;c变量引入了CStr外部接口,通过CStr::from_ptr(c_ptr)
获取一个以\0
结尾的C语言类型的字符串;b和c变量都需要把[u8, n]
先转换成*const u8
在转换成所需的相应指针类型; - Rust的裸指针分为
*const T
和*mut T
,分别是不可变裸指针和可变裸指针,两者之间可以自由转换,Rust的引用&mut T and &T
编译出来的结果就成了裸指针,也就是在实际运行过程中不需要通过unsafe也能得到裸指针的性能; - 使用裸指针的原因:不可避免的使用,当需要系统调用OS功能或者某些第三方代码需要裸指针,一般是对C写的一些程序的外部调用;需要多个地方同时访问数据并且对运行时性能要求极高的时候;
- C++中的智能指针在Rust中对应的是
core::ptr::{Unique, Shared, Weak}
,胖指针(fat pointer)通常指内存布局,对比瘦指针(thin pointer,通常也指裸指针,只有一个usize宽度),要更大一些,通常有2个usize宽度甚至更多; core::ptr::Unique
是rust中String, Box<T>
的构成要素;core::ptr::Shared
是Rc<T>, Arc<T>
的构成要素,如果要实现自己的智能指针,可以参考这些智能指针的实现细节;std::rc::Weak, std::arc::Weak
可用于内部互相指向的数据结构,避免循环指针的问题;alloc::raw_vec::RawVec
用于实现了Vec<T>, VecDeq<T>
,它能够很聪明地给任何类型的数据分配和回收内存;std::cell::UnsafeCell
用于实现Cell<T>, RefCell<T>
,来提供内部可变性(interior mutability);- "When in doubt, prefer the stack"表示了当不知道把数据放在堆上还是栈上时,优先放在栈上,因为栈比较快,这句话的Rust版本是,
When in doulbe, use types that implement Sized
,即实现了Sized特征的类型会优先放在栈上存储; - 如何让一个函数同时接受
&str, String
两种类型的参数,可以使用参数模板<T: AsRef<str>>
表示参数T可以称为str的引用,从而调用.as_ref().len()
方法,详细可见Page189; - 表6.1给出了简单的栈和堆的对比,注意表中说明了在没有Unsafe的Rust中,使用堆是安全的;
- 几个通用的优化堆内存分配的方法:提前分配好足够的空间,将其初始化为0,到使用的时候再将其改为非0值,这种方法比较危险,可能会引发Rust的生命周期检查;自己针对程序设计一个allocator,能更有效地分配出所需的空间;调研使用
arena::{Arena, TypedArena}
,允许对象边创建边使用(created on the fly),arena是一个第三方库,链接; - 虚拟内存常用术语,页(Page)、字(Word)、页错误(Page fault)、交换(Swapping)、虚拟内存(Virtual memory)、实际内存(Real memory)、页表(Page table)、段(Segment)、段错误(Segmentation fault)、MMU、TLB(translation lookaside buffer),详见Page203;
- 6.4.2节讲了段错误(segmentation fault),当访问一个非法区域时会产生,可以参考下代码实现;
- 6.4.3节讲了MMU(memory mamagement unit)的作用,即把虚拟地址翻译成物理地址,以及使用TLB缓存加速的作用, 206页讲了操作系统和CPU在翻译地址过程中用到的一些小tricks;
- 下图讲了一个可执行文件(ELF)是如何加载到虚拟内存并运行的过程