当前位置:嗨网首页>书籍在线阅读

52-mem模块

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

7.12.2 std::mem模块

关于类型及其在内存中的大小,标准库中的mem模块为我们提供了方便的API,用于检查初始化原始内存的类型大小和功能的对齐方式。这些函数中有相当一部分是不安全的,只有当程序员知道它们在做什么时才能使用。我们将限制对这些API的探索。

  • size_of返回通过泛型获得的类型大小。
  • size_of_val返回某个引用值的大小。

通常,这些方法是通过turbofish运算符::<>调用的。我们实际上并没有给这些方法提供某个类型作为参数;只是显式针对某种类型调用它们。如果我们对前面的某些零成本的泛型声明存在疑问,那么可以使用这些函数检查它们的内存开销情况。让我们看看Rust中某些类型的大小:

// mem_introspection.rs
use std::cell::Cell;
use std::cell::RefCell;
use std::rc::Rc;
fn main() {
    println!("type u8: {}", std::mem::size_of::<u8>());
    println!("type f64: {}", std::mem::size_of::<f64>());
    println!("value 4u8: {}", std::mem::size_of_val(&4u8));
    println!("value 4: {}", std::mem::size_of_val(&4));
    println!("value 'a': {}", std::mem::size_of_val(&'a'));
    println!("value \"Hello World\" as a static str slice: {}",
std::mem::size_of_val("Hello World"));
    println!("value \"Hello World\" as a String: {}",
std::mem::size_of_val("Hello World").to_string());
    println!("Cell(4)): {}", std::mem::size_of_val(&Cell::new(84)));
    println!("RefCell(4)): {}", std::mem::size_of_val(&RefCell::new(4)));
    println!("Rc(4): {}", std::mem::size_of_val(&Rc::new(4)));
    println!("Rc<RefCell(8)>): {}",
std::mem::size_of_val(&Rc::new(RefCell::new(4))));
}

需要重点关注的一点是各指针的大小。请考虑如下代码:

// pointer_layouts.rs
trait Position {}
struct Coordinates(f64, f64);
impl Position for Coordinates {}
fn main() {
    let val = Coordinates(1.0, 2.0);
    let ref_: &Coordinates = &val;
    let pos_ref: &Position = &val as &Position;
    let ptr:       *const Coordinates = &val as *const Coordinates;
    let pos_ptr: *const Position = &val as *const Position;
    println!("ref_: {}", std::mem::size_of_val(&ref_));
    println!("ptr: {}", std::mem::size_of_val(&ptr));
    println!("val: {}", std::mem::size_of_val(&val));
    println!("pos_ref: {}", std::mem::size_of_val(&pos_ref));
    println!("pos_ptr: {}", std::mem::size_of_val(&pos_ptr));
}

我们以一系列不同的方式创建指向结构体Coordinates的指针,并将它们转换为不同类型的指针后输出其大小。编译并运行上述代码后,得到了以下输出结果:

ref_: 8
ptr: 8
val: 16
pos_ref: 16
pos_ptr: 16

这清楚地表明,特征对象和指向特征的引用是胖指针,它们是普通指针大小的两倍。