Rust中的特殊类型(引用、智能指针等)所占的内存大小

本文分析了Rust中不同类型的引用/智能指针在内存中所占空间大小,主要包含:

  • 普通结构体的引用 / 智能指针
  • 特征对象的引用 / 智能指针 / 裸指针
  • 几种切片类型(字符串切片&str / 数组切片&[i32] / 静态数组引用&[i32; N])
  • 几种集合类型(静态数组[i32; N] / 动态数组Vec / 字符串String)

可以使用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::<Box<Journal>>());

    println!("特征对象相关:");
    println!("{}", size_of::<Box<dyn Summary>>());
    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::<Vec<i32>>());
    println!("{}", size_of::<String>());
}

输出

普通结构体相关:
8
8
特征对象相关:
16
16
16
16
16
切片相关:
16
16
8
集合相关:
400
24
24

原因分析

Rust中,一个普通指针的大小为usize,与计算机CPU字长相等,对64位计算机来说usize=64/8=8字节

  • 对普通结构体来说,其引用/Box智能指针所占大小为usize,指示在内存中的起始位置即可,因为普通结构体编译时大小确定,运行时存放在栈上
  • 特征对象非常特殊,其引用/Box智能指针/裸指针占的大小均为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<u8>的封装,其数据存放在堆上,String类型占三个usize的长度,分别指示字符串在堆中的起始位置,字符串长度以及字符串当前的最大长度

其实,VecString的本质都是智能指针,它们的大小都是固定的(大小不固定也没法通过编译啊),运行时存放在栈上。但是它们所包裹数据的长度是可变的,存放在堆上。它们的本质是通过存放在栈上的指针访问堆内存,来操作堆上包裹的数据。

综上所述,智能指针/引用所占内存大小是固定的,但是其指向的数据大小未必固定。对于所占内存固定已知的数据类型,运行时会把它们放在栈上,对于所占内存不固定的数据类型,运行时会把它们放在堆上,然后可以通过存放在栈上的指针来操作堆上的数据。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值