【Rust 基础篇】Rust Sized Trait:理解Sized Trait与动态大小类型
导言
Rust是一门以安全性和性能著称的系统级编程语言。在Rust中,类型大小的确定在编译期是非常重要的。然而,有些类型的大小在编译期是无法确定的,这就涉及到了Rust中的动态大小类型(DST)。为了保证在编译期可以确定类型的大小,Rust引入了Sized trait。本篇博客将深入探讨Rust中的Sized trait,包括Sized trait的定义、作用、使用方法,以及Sized trait与动态大小类型的关系,以便读者全面了解Rust中的类型大小问题,编写更安全、高效的代码。
1. 什么是Sized Trait?
在Rust中,Sized是一个特殊的trait,它用于标识类型是否在编译期已知大小。Sized trait的定义如下:
pub trait Sized {// 该trait没有任何方法,用于标识类型是否具有确定的大小
}
需要注意的是,所有的类型默认都是Sized的,除非使用特殊语法来标识为不具有确定大小的动态大小类型。
2. 动态大小类型与Sized Trait的关系
在Rust中,动态大小类型(DST)是一种特殊的类型,它的大小在编译期无法确定,需要在运行时根据实际情况确定。动态大小类型主要包括引用类型和trait对象。而Sized trait用于标识类型是否在编译期已知大小。
2.1 引用类型与Sized Trait
引用类型是Rust中的动态大小类型之一。在Rust中,引用类型是通过引用(&)来引用其他类型的值。引用类型的大小在编译期是无法确定的,因为它的大小取决于被引用的值的大小。
fn main() {let x = 42;let reference = &x; // 引用x的值
}
在上述例子中,我们创建了一个变量x
,然后通过引用(&)创建了一个引用reference
,引用了变量x
的值。引用类型的大小在编译期无法确定,因为它的大小取决于被引用的值的大小。
然而,引用类型并不是一个动态大小类型,因为它并没有在编译期确定大小的问题。引用类型总是具有固定的大小,即&T
类型的大小总是等于指针的大小。这是因为引用的值总是存在于堆栈中,而不是存储在引用本身中。
2.2 trait对象与Sized Trait
trait对象是Rust中的另一种动态大小类型。在Rust中,trait对象是通过trait来引用具体类型的值,使得这些值可以按照相同的trait进行操作。trait对象的大小在编译期是无法确定的,因为它的大小取决于具体类型的大小。
trait Shape {fn area(&self) -> f64;
}struct Circle {radius: f64,
}impl Shape for Circle {fn area(&self) -> f64 {self.radius * self.radius * std::f64::consts::PI}
}fn main() {let circle: Circle = Circle { radius: 5.0 };let shape: &dyn Shape = &circle; // 通过trait对象引用具体类型的值
}
在上述例子中,我们定义了一个trait Shape
,并为具体类型Circle
实现了该trait。然后,我们通过trait对象&dyn Shape
来引用具体类型Circle
的值。trait对象的大小在编译期无法确定,因为它的大小取决于具体类型的大小。
在trait对象中,存在一个隐藏的指针,用于存储具体类型的值,并通过该指针来调用具体类型的方法。因此,trait对象的大小是固定的,即&dyn Trait
类型的大小等于一个指针的大小。
2.3 Sized Trait的限制
在Rust中,动态大小类型(DST)有一些限制,特别是在泛型和trait实现中。
2.3.1 泛型中的Sized Trait限制
在泛型中,如果要使用动态大小类型,则需要使用?Sized
语法来标识。
// 错误示例:无法使用动态大小类型作为泛型参数
fn process_data<T>(data: &[T]) {// 处理数据
}fn main() {let vec_data = vec![1, 2, 3, 4, 5];process_data(&vec_data); // 编译错误:动态大小类型不能用作泛型参数
}
在上述错误示例中,我们尝试在泛型函数process_data
中使用动态大小类型[T]
作为参数,但这是不允许的。为了允许使用动态大小类型作为泛型参数,我们需要使用?Sized
语法来标识。
// 正确示例:使用动态大小类型作为泛型参数
fn process_data<T: ?Sized>(data: &[T]) {// 处理数据
}fn main() {let vec_data = vec![1, 2, 3, 4, 5];process_data(&vec_data); // 正确:使用动态大小类型作为泛型参数
}
在上述正确示例中,我们使用了?Sized
语法来标识T
可以是动态大小类型,从而允许使用动态大小类型作为泛型参数。
2.3.2 trait实现中的Sized Trait限制
在Rust中,为了安全性考虑,如果要为trait实现动态大小类型,必须使用?Sized
语法来标识。这是因为对于trait对象,编译器需要在运行时动态地确定具体类型的大小,而不是在编译期确定。
trait Shape {fn area(&self) -> f64;
}struct Circle {radius: f64,
}impl Shape for Circle {fn area(&self) -> f64 {self.radius * self.radius * std::f64::consts::PI}
}// 错误示例:无法为trait实现动态大小类型
impl Shape for dyn Shape {fn area(&self) -> f64 {// 实现trait方法}
}fn main() {let circle: Circle = Circle { radius: 5.0 };let shape: &dyn Shape = &circle;shape.area();
}
在上述错误示例中,我们尝试为trait Shape
实现动态大小类型,但这是不允许的。为了允许为trait实现动态大小类型,我们需要使用?Sized
语法来标识。
// 正确示例:使用?Sized语法为trait实现动态大小类型
impl Shape for dyn Shape + ?Sized {fn area(&self) -> f64 {// 实现trait方法}
}fn main() {let circle: Circle = Circle { radius: 5.0 };let shape: &dyn Shape = &circle;shape.area();
}
在上述正确示例中,我们使用了?Sized
语法来标识dyn Shape
可以是动态大小类型,从而允许为trait实现动态大小类型。
3. 使用方法
3.1 检查类型是否满足Sized Trait
在Rust中,我们可以使用is_sized
函数来检查类型是否满足Sized Trait。
fn main() {println!("i32 is Sized: {}", std::mem::size_of::<i32>() == std::mem::size_of::<i32>());println!("&i32 is Sized: {}", std::mem::size_of::<&i32>() == std::mem::size_of::<usize>());
}
在上述例子中,我们使用is_sized
函数来检查i32
和&i32
是否满足Sized Trait。由于i32
是Sized类型,因此输出为true
,而&i32
是引用类型,也是Sized类型,输出为true
。
3.2 使用Sized Trait来约束泛型
在泛型中,我们可以使用Sized Trait来约束类型是否满足Sized。
fn process_data<T: Sized>(data: &[T]) {// 处理数据
}fn main() {let vec_data = vec![1, 2, 3, 4, 5];process_data(&vec_data); // 正确:Sized类型作为泛型参数
}
在上述例子中,我们使用Sized Trait来约束泛型函数process_data
的参数类型,确保只有Sized类型才能作为泛型参数。
3.3 使用?Sized来实现动态大小类型
当需要为trait实现动态大小类型时,可以使用?Sized
语法来标识。
trait Shape {fn area(&self) -> f64;
}struct Circle {radius: f64,
}impl Shape for Circle {fn area(&self) -> f64 {self.radius * self.radius * std::f64::consts::PI}
}impl Shape for dyn Shape + ?Sized {fn area(&self) -> f64 {// 实现trait方法}
}fn main() {let circle: Circle = Circle { radius: 5.0 };let shape: &dyn Shape = &circle;shape.area();
}
在上述例子中,我们使用了?Sized
语法来标识dyn Shape
可以是动态大小类型,从而允许为trait实现动态大小类型。
4. 动态大小类型与Sized Trait的比较
虽然动态大小类型和Sized Trait都涉及到类型大小的确定,但它们有着不同的含义和用途。
动态大小类型是一种特殊的类型,它的大小在编译期无法确定,需要在运行时根据实际情况确定。动态大小类型主要包括引用类型和trait对象。在使用动态大小类型时,需要注意其限制,如无法直接实例化、泛型中的限制等。
而Sized Trait是一个特殊的trait,用于标识类型是否在编译期已知大小。所有的类型默认都是Sized的,除非使用特殊语法来标识为不具有确定大小的动态大小类型。Sized Trait的作用是用于泛型和trait实现中,约束类型是否满足Sized。
结论
本篇博客对Rust中的Sized Trait进行了深入解释和说明,包括Sized Trait的定义、作用、使用方法,以及与动态大小类型的关系和比较。Sized Trait在Rust中是一个非常重要的概念,它用于标识类型是否在编译期已知大小,保证类型的大小在编译期可以确定。通过深入理解和正确使用Sized Trait,我们可以编写更安全、高效的代码,充分发挥Rust语言的优势。希望通过本篇博客的阐述,读者能够全面了解Rust中的Sized Trait,为编写优秀的Rust代码打下坚实的基础。谢谢阅读!
相关文章:
【Rust 基础篇】Rust Sized Trait:理解Sized Trait与动态大小类型
导言 Rust是一门以安全性和性能著称的系统级编程语言。在Rust中,类型大小的确定在编译期是非常重要的。然而,有些类型的大小在编译期是无法确定的,这就涉及到了Rust中的动态大小类型(DST)。为了保证在编译期可以确定类…...
前端框架学习-Vue(三)
目录 初识VueVue模板语法数据绑定el和data的两种写法事件的基本使用$emit在子组件中定义方法,执行父组件的方法 Vue中的事件修饰符:键盘事件计算属性监视属性条件渲染列表渲染表单数据收集过滤器 笔记内容来自:尚硅谷Vue2.0Vue3.0全套教程丨v…...
HTML <rt> 标签
实例 一个 ruby 注释: <ruby> 漢 <rt> ㄏㄢˋ </rt> </ruby>浏览器支持 元素ChromeIEFirefoxSafariOpera<rt>5.05.538.05.015.0 Internet Explorer 9, Firefox, Opera, Chrome 以及 Safari 支持 <rt> 标签。 注释…...

VMware Linux Centos 配置网络并设置为静态ip
在root用户下进行以下操作 1. 查看子网ip和网关 (1)进入虚拟网络编辑器 (2)进入NAT设置 (3)记录子网IP和子网掩码 2. 修改网络配置文件 (1)cd到网络配置文件路径下 [rootlo…...
【Leetcode 30天Pandas挑战】学习记录
这个系列难度比较低,一题写一篇其实没必要,就全部放到一篇吧 题目列表: 595. Big Countries1757. Recyclable and Low Fat Products 595. Big Countries 原题链接:595. Big Countries Table: World ---------------------- | C…...

微信小程序使用 canvas 2d 实现签字板组件
本文是在微信小程序中使用 canvas 2d 来实现签字板功能; 效果图: 代码: 1、wxml <view><canvas id"canvas"type"2d"bindtouchstart"start"bindtouchmove"move"bindtouchend"end&qu…...
区块链赋能新时代司法体系,中移链打造可信存证服务
近期,某百万级粉丝网红的法律维权之路引发社会关注。其在面对网络造谣行为时积极搜集证据,使用区块链技术将相关信息上链保全,然后将造谣者全部起诉,一系列操作被广大网友喻为是教科书式网络维权。 科技在发展,时代在…...

ELK报错no handler found for uri and method [PUT] 原因
执行后提示no handler found for uri and method post,最新版8.2的问题? 原因: index.mapping.single_type: true在索引上 设置将启用按索引的单一类型行为,该行为将在6.0后强制执行。 原 {type} 要改为 _doc,格式如…...

Sublime操作技巧笔记
同时选中2个文件:自动切换成左右2个界面 格式化代码ctrlshifth: 使用快捷键ctrl shift p调出控制台,输入install package,然后输入html-css-js prettify,进行下载。具体的快捷键在preference > package setting &g…...

JVM | 基于类加载的一次完全实践
引言 我在上篇文章:JVM | 类加载是怎么工作的 中为你介绍了Java的类加载器及其工作原理。我们简单回顾下:我用一个易于理解的类比带你逐步理解了类加载的流程和主要角色:引导类加载器,扩展类加载器和应用类加载器。并带你深入了解…...
Termux实现电脑端远程操作【开启SSH的完整教程】
文章目录 前言一、安装软件1、安装2、启动服务3、特别说明4、添加key二、电脑端连接1、查看ip2、电脑端连接总结前言 上篇文章【安卓手机变身Linux服务器】讲了如何将你的上古安卓手机变废为宝,这节着重为大家解决一个痛点:“手机上操作实在是不方便”。 一、安装软件 1、安…...

java(Collection类)
文章目录 Collection接口继承树Collection接口及方法判断删除其它 Iterator(迭代器)接口迭代器的执行原理 foreach循环Collection子接口1:ListList接口特点List接口方法List接口主要实现类:ArrayListList的实现类之二:LinkedListList的实现类…...
VS2019编译安装OpenMesh8.0
文章目录 一、简介二、相关准备三、编译安装四、举个栗子参考资料一、简介 多边形网格一直以来就是交互式3D图形应用程序中最合适的几何表示,它们足够灵活,可以近似任意形状,并且可以通过当前的图形硬件有效地处理,即使在今天的低成本电脑上也是如此。OpenMesh便是其中一种…...

Python爬虫遇到URL错误解决办法大全
在进行Python爬虫任务时,遇到URL错误是常见的问题之一。一个错误的URL链接可能导致爬虫无法访问所需的网页或资源。为了帮助您解决这个问题,本文将提供一些实用的解决方法,并给出相关代码示例,希望对您的爬虫任务有所帮助。 一、…...

基于Vue+ElementUI+Echarts+G2Plot的大屏设计器,代码完全开源
简介 🔥DataRoom是一款基于SpringBoot、MyBatisPlus、ElementUI、G2Plot、Echarts等技术栈的大屏设计器,具备大屏设计、预览、资源管理、组件管理等能力,支持JSON、MySQL、Oracle、PostgreSQL、HTTP、JavaScript、Groovy等数据集接入&#x…...

Linux - PostgreSQL 适用于9.x 以上的 tar.gz 源码安装与理解 - 报错集锦
这里写目录标题 序言主要内容bash 配置文件个人理解关于初始化 PostgreSQL 数据库的理解 启动方法检查服务器是否在PostgreSQL中运行关闭 postgresql 数据库方法参考链接 序言 PostgreSQL 9.x 以下版本笔者没用过,具体操作看参考链接,笔者就不记录重复操…...

Django使用用户列表的展示和添加
接着上一篇:https://blog.csdn.net/javascript_good/article/details/132027702 来实现用户表的查询和添加 1、创建数据库表 在models.py 中,增加UserInfo类,包括字段姓名、密码、年龄、账号余额、入职时间、所属部门、性别 verbose_name 就…...
kubernetes错误汇总
title: “kubernetes错误汇总” categories: - “技术” tags: - “Kubernetes” - “错误汇总” toc: false original: true draft: false 1、增加 master etcd 报错 1.1、错误描述 由于创建的k8s集群,其中有一个master节点初始化失败,先删除了这个节…...

[openCV]基于拟合中线的智能车巡线方案V4
import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir:文件夹根目录输入 ext: 扩展名返回: 文件路径列表"""newDir d…...

【网络云盘客户端】——上传文件的功能的实现
目录 上传文件功能的实现 uploadtask的设计 设置上传的槽函数 uploadFileAction接口 uploadFile接口 定时上传文件 进度条的设计 上传文件功能的实现 上传文件功能实现 1.双击 ”上传文件 “的 QListWidgetItem 或者 点击 “上传” 菜单项 都会弹出一个文件对话框 2.在文…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...