当前位置: 首页 > news >正文

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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • WebStorm格式化JSON,将一行很长的JSON展开
  • 在vscode中远程连接linux进行开发
  • 数据结构与算法--递归
  • Terminator的分割终端功能确实非常实用,特别是当你需要同时监控多个任务时,快捷键来分割窗口
  • 计算机专业英语词汇
  • 无人机长生不老秘籍
  • C++之移动语义与左值右值深入学习:从入门到精通!
  • leetcode每日一题46
  • 《数据结构》(C语言版)第1章 绪论(下)
  • C语言 ——— 在控制台实现扫雷游戏(一次展开一片,递归实现)
  • java之静态内部类
  • 国内顶级 AI 的回答令人“贻笑大方”:看来苹果秃头码农们暂时还不会失业吧?
  • vue3+vite全局引入less变量和函数
  • playwrite今日头条自动发帖
  • 未授权访问漏洞
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • 2017届校招提前批面试回顾
  • CentOS6 编译安装 redis-3.2.3
  • create-react-app项目添加less配置
  • express.js的介绍及使用
  • Flannel解读
  • magento2项目上线注意事项
  • Map集合、散列表、红黑树介绍
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • node和express搭建代理服务器(源码)
  • PHP面试之三:MySQL数据库
  • sublime配置文件
  • underscore源码剖析之整体架构
  • use Google search engine
  • 前言-如何学习区块链
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 如何邀请好友注册您的网站(模拟百度网盘)
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 1.Ext JS 建立web开发工程
  • AI算硅基生命吗,为什么?
  • Mac 上flink的安装与启动
  • MPAndroidChart 教程:Y轴 YAxis
  • 我们雇佣了一只大猴子...
  • 正则表达式-基础知识Review
  • ​虚拟化系列介绍(十)
  • #include<初见C语言之指针(5)>
  • (007)XHTML文档之标题——h1~h6
  • (09)Hive——CTE 公共表达式
  • (11)MSP430F5529 定时器B
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (2024)docker-compose实战 (9)部署多项目环境(LAMP+react+vue+redis+mysql+nginx)
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (ZT)薛涌:谈贫说富
  • (八十八)VFL语言初步 - 实现布局
  • (一一四)第九章编程练习
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • ****** 二十三 ******、软设笔记【数据库】-数据操作-常用关系操作、关系运算
  • ******IT公司面试题汇总+优秀技术博客汇总