std::mem:size_of获取类型大小:use std::mem::size_of; struct Journal(String, u32); trait Summary {} impl Summary for Journal {} fn main() { println!("普通结构体相关:"); println!("{}", size_of::<&Journal>()); println!("{}", size_of::>()); println!("特征对象相关:"); println!("{}", size_of::>()); println!("{}", size_of::<&dyn Summary>()); println!("{}", size_of::<&mut dyn Summary>()); println!("{}", size_of::<*const dyn Summary>()); println!("{}", size_of::<*mut dyn Summary>()); println!("切片相关:"); println!("{}", size_of::<&str>()); println!("{}", size_of::<&[i32]>()); println!("{}", size_of::<&[i32; 100]>()); println!("集合相关:"); println!("{}", size_of::<[i32; 100]>()); println!("{}", size_of::>()); println!("{}", size_of::()); } 普通结构体相关: 8 8 特征对象相关: 16 16 16 16 16 切片相关: 16 16 8 集合相关: 400 24 24 Rust中,一个普通指针的大小为usize,与计算机CPU字长相等,对64位计算机来说usize=64/8=8字节
usize,指示在内存中的起始位置即可,因为普通结构体编译时大小确定,运行时存放在栈上2*usize&str所占空间为2*usize,所引用字符串可能来自于堆内存/全局数据区,&str指示了所引用数据的起始位置和长度&[i32]与&str类似(&str是对&[u8]的封装),所占空间为2*usize,指示了所引用字符串在堆内存/栈内存中的起始位置和长度&[i32; N]仅占一个usize,因为[i32; N]编译时大小已知,存放在栈上,&[i32; N]不需要像&[i32]那样额外记录长度[i32; 100]编译时大小已知,存放在栈上,内存大小为4*100=400个字节Vec动态数组的数据存放在堆上,Vec类型占三个usize的长度,分别指示数组在堆中的起始位置,数组长度以及数组当前的最大容量String是对Vec的封装,其数据存放在堆上,String类型占三个usize的长度,分别指示字符串在堆中的起始位置,字符串长度以及字符串当前的最大长度其实,Vec和String的本质都是智能指针,它们的大小都是固定的(大小不固定也没法通过编译啊),运行时存放在栈上。但是它们所包裹数据的长度是可变的,存放在堆上。它们的本质是通过存放在栈上的指针访问堆内存,来操作堆上包裹的数据。
综上所述,智能指针/引用所占内存大小是固定的,但是其指向的数据大小未必固定。对于所占内存固定已知的数据类型,运行时会把它们放在栈上,对于所占内存不固定的数据类型,运行时会把它们放在堆上,然后可以通过存放在栈上的指针来操作堆上的数据。