rust的类型转换和一些智能指针用法(四)

基础类型

使用 as 关键字:用于基本数值类型之间的转换,例如将 i32 转换为 u32。
例子:let x: i32 = 10; let y: u64 = x as u64;
使用标准库中的转换方法:如 from()into() 方法,这些方法通常用于无风险的转换,或者当转换可能失败时返回 Result 类型。
例子:let x: i32 = 10; let y: u64 = u64::from(x);(如果转换是安全的)
使用 try_into()try_from():当转换有可能失败时(例如,当试图将较大的整数类型转换为较小的整数类型时),这些方法会返回一个 Result 类型,允许错误处理。
例子:let x: i32 = 10; let y: u8 = x.try_into().unwrap();
布尔类型转换
布尔类型不能直接转换为数值类型,也不能从数值类型直接转换。
如果需要基于布尔值生成数值,可以使用条件表达式:let num = if bool_val { 1 } else { 0 };
字符与数值类型转换
字符类型 (char) 与整数类型之间的转换也需要显式操作。
例子:将 char 转换为其对应的 Unicode 编码(一个整数):let num = 'a' as u32;
从整数转换到 char 时需要保证整数是一个有效的 Unicode 码点:let ch = std::char::from_u32(97).unwrap();
元组和数组
元组和数组的转换通常涉及到元素的解构或重新组合,而不是类型转换。
例如,从元组转换到不同类型的元组或提取元组中的值:let tup = (1, 2.0, 'a'); let (x, y, z) = tup;

其他类型转字符串

1.使用 to_string() 方法
这是转换任何实现了 Display trait 的类型到字符串的最简单和最直接的方法。i32 和 f64 都实现了 Display trait,所以可以直接使用 to_string() 方法。

let num_i32 = 32;
let num_f64 = 10.5;let str_from_i32 = num_i32.to_string();
let str_from_f64 = num_f64.to_string();println!("i32 to String: {}", str_from_i32);  // 输出:i32 to String: 32
println!("f64 to String: {}", str_from_f64);  // 输出:f64 to String: 10.5

2.使用 format! 宏

let num_i32 = 32;
let num_f64 = 10.5;// 使用 format! 宏进行基本转换
let str_from_i32 = format!("{}", num_i32);
let str_from_f64 = format!("{}", num_f64);// 使用 format! 宏指定浮点数的精度
let formatted_f64 = format!("{:.2}", num_f64);println!("i32 to String: {}", str_from_i32);  // 输出:i32 to String: 32
println!("f64 to String: {}", str_from_f64);  // 输出:f64 to String: 10.5
println!("Formatted f64: {}", formatted_f64);  // 输出:Formatted f64: 10.50

字符串转整形,或者浮点型

let s = "42".to_string();
let result: Result<i32, _> = s.parse();
match result {Ok(num) => println!("Converted string to i32: {}", num),Err(e) => println!("Failed to convert string to i32: {}", e),
}let s = "3.14".to_string();
let result: Result<f64, _> = s.parse();
match result {Ok(num) => println!("Converted string to f64: {}", num),Err(e) => println!("Failed to convert string to f64: {}", e),
}

Result 和 Option 核心枚举类型常用的方法

Option
Option<T>
Option<T> 类型用于可能存在或可能不存在的值。它有两个变体:Some(T) 表示有一个值,和 None 表示没有值。常用方法:unwrap():提取 Some 的值或在 None 时引发 panic。
let some_option = Some("Hello");
println!("{}", some_option.unwrap());  // 输出 "Hello"unwrap_or():提取 Some 的值或在 None 时返回一个默认值。
let none_option: Option<&str> = None;
println!("{}", none_option.unwrap_or("Default"));  // 输出 "Default"map():如果是 Some(T),应用一个函数到内部值并返回一个新的 Optionlet num_option = Some(5);
let squared = num_option.map(|x| x * x);
println!("{:?}", squared);  // 输出 Some(25)and_then():如果是 Some(T),则应用一个返回 Option<U> 的函数,否则返回 None
let some_string = Some("5");
let parsed = some_string.and_then(|s| s.parse::<i32>().ok());
println!("{:?}", parsed);  // 输出 Some(5)
Result
unwrap():提取 Ok 的值或在 Err 时引发 panic。
let ok_result: Result<i32, &str> = Ok(10);
println!("{}", ok_result.unwrap());  // 输出 10unwrap_or():提取 Ok 的值或在 Err 时返回一个默认值。
let err_result: Result<i32, &str> = Err("error");
println!("{}", err_result.unwrap_or(0));  // 输出 0map():如果是 Ok(T),应用一个函数到内部值并返回一个新的 Resultlet ok_result = Ok(2);
let doubled = ok_result.map(|x| x * 2);
println!("{:?}", doubled);  // 输出 Ok(4)and_then():如果是 Ok(T),则应用一个返回 Result<U, E> 的函数,否则返回 Err(E)
let ok_result = Ok("10");
let parsed = ok_result.and_then(|s| s.parse::<i32>().map_err(|e| "parse error"));
println!("{:?}", parsed);  // 输出 Ok(10)or_else():如果是 Err(E),应用一个函数来创建一个新的 Result,否则保持 Ok(T)
let err_result: Result<i32, &str> = Err("error");
let fixed = err_result.or_else(|_| Ok(0));
println!("{:?}", fixed);  // 输出 Ok(0)
if let
let some_option = Some(10);if let Some(value) = some_option {println!("Got a value: {}", value);
} else {println!("Got nothing!");
}let result: Result<i32, String> = Ok(20);if let Ok(num) = result {println!("Success with number: {}", num);
} else {println!("Failed!");
}let some_string = Some("Hello, World!");if let Some(length) = some_string.map(|s| s.len()) {println!("The string length is: {}", length);
} else {println!("No string!");
}let result: Result<i32, String> = Err("Something went wrong".to_string());if let Err(e) = result {println!("Error occurred: {}", e);
}
// 也可以添加一个 else 分支处理成功情况
else {println!("Success, no errors!");
}let result: Result<i32, String> = Err("failed".to_string());// 使用 map_err 转换错误类型,然后使用 if let 检查
if let Err(e) = result.map_err(|e| format!("Error: {}", e)) {println!("{}", e);
}

常用智能指针

Box 在 Rust 中是一个非常有用的类型,它允许你将数据放在堆上而不是栈上

常用的几个场景

1. 处理大数据
当你有一个非常大的数据结构时,将其放在栈上可能会导致栈溢出或不必要的性能负担。使用 Box 可以避免这些问题,因为它将数据存储在堆上。示例:
let large_array = Box::new([0u8; 1000000]);  // 1MB的空间
这里,一个大型的数组被分配在堆上,而不是占用宝贵的栈空间。2. 递归类型
在定义递归数据结构时,比如链表或树,你通常需要使用 Box 来间接持有类型的一部分。这是因为 Rust 需要在编译时知道类型的确切大小,而递归类型无法在不进行某种形式的间接寻址的情况下给出确切大小。示例:
enum List<T> {Cons(T, Box<List<T>>),Nil,
}use List::{Cons, Nil};let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
这里的链表 List 使用 Box 来持有其递归部分,这使得 Rust 能够处理变量大小的类型。3. 确保类型拥有 trait 对象
当你需要创建一个动态分发的类型时,通常需要使用 trait 对象。Trait 对象(如 Box<dyn SomeTrait>)允许你在运行时存储和调用实现了该 trait 的任何类型的实例。示例:trait Speak {fn speak(&self);
}struct Dog;
struct Cat;impl Speak for Dog {fn speak(&self) {println!("Woof!");}
}impl Speak for Cat {fn speak(&self) {println!("Meow!");}
}let animals: Vec<Box<dyn Speak>> = vec![Box::new(Dog),Box::new(Cat),
];for animal in animals {animal.speak();
}
在这个示例中,不同类型的动物都实现了 Speak trait,并且通过 Box<dyn Speak> 存储在同一个向量中,使得可以在运行时动态地调用它们的 speak 方法。4. 接口的强制所有权
有时,你可能想要确保某个函数完全拥有它接收的数据,Box<T> 可以用来明确这种所有权转移。示例:
fn process_data(data: Box<Data>) {// 处理数据
}let data = Box::new(Data::new());
process_data(data);
RefCell 与 Rc 的使用

这种组合允许在单线程环境中实现多个可变引用的共享数据。Rc 本身不允许可变引用,因为它只保证数据的多所有者共享,而不提供数据修改的能力。结合 RefCell,它提供了一种运行时检查的方式来借用可变或不可变的引用。

示例:使用 RefCell 与 Rc
假设我们有一个结构体 Person,它存储在多个地方,并且我们希望在运行时根据需要修改其字段:

use std::rc::Rc;
use std::cell::RefCell;struct Person {name: String,age: u32,
}fn main() {let person = Rc::new(RefCell::new(Person {name: "Alice".to_string(),age: 30,}));{let mut p = person.borrow_mut();p.age += 1;}{let p = person.borrow();println!("{} is {} years old.", p.name, p.age);}
}

例子2 ,共享多个写入和读取

use std::rc::Rc;
use std::cell::RefCell;struct TextBox {content: Rc<RefCell<String>>,
}impl TextBox {fn new(content: &Rc<RefCell<String>>) -> TextBox {TextBox {content: Rc::clone(content),}}fn display(&self) {println!("{}", self.content.borrow());}fn append(&self, text: &str) {println!("Before append: {}", self.content.borrow());self.content.borrow_mut().push_str(text);println!("After append: {}", self.content.borrow());}
}fn main() {let shared_text = Rc::new(RefCell::new(String::from("Hello")));let text_box1 = TextBox::new(&shared_text);text_box1.append(" world");text_box1.append(" gitxuzan");let text_box2 = TextBox::new(&shared_text);text_box2.display(); // 应该输出 "Hello world gitxuzan"
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/24996.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

11本AI人工智能相关电子书推荐(带下载地址)

1. 《生命3.0》 电子书链接&#xff1a;百度网盘 请输入提取码 提取码: vxnw 2. 《千脑智能》 电子书链接&#xff1a; 百度网盘 请输入提取码 提取码: we8u 3. 《AI 3.0》 电子书链接&#xff1a; 百度网盘 请输入提取码 提取码: nwu4 4. 《元宇宙与数字经济》 电子书链接…

【算法小记】深度学习——时间序列数据分析 Time series Data Analysis

在本篇博客中将简单介绍常见的几种循环神经网络和一维卷积神经网络&#xff0c;并使用一些简答的数据进行拟合分析。本文相对适合刚入门的同学&#xff0c;同时也作为自己过去一段时间学习的总结和记录&#xff0c;现在神经网络框架已经非常完善的支持了很多常见和有效的深度学…

【优选算法】BFS解决FloodFill算法

一、经验总结 什么是FloodFill算法&#xff1f; FloodFill算法是一种用于填充连通区域的算法&#xff0c;通常用于图像处理和计算机图形学中。它从给定的起始点开始&#xff0c;向周围相邻的像素进行扩散填充&#xff0c;直到遇到边界或者其他指定条件停止。 FloodFill算法还…

TCP/IP 接收发送缓存大小的自动调优 Auto Tuning

内部机制已实现自动调整缓存大小。参考Tuning the network。 1. net.ipv4.tcp_moderate_rcvbuf 是 Linux 内核的一个参数,用于控制 TCP 接收缓冲区大小的自动调整。 当这个参数被激活时,Linux 内核会根据当前网络条件自动调整 TCP 接收缓冲区的大小,以优化网络性能。它会根…

新买的移动硬盘无法识别

文章目录 背景解决方案 背景 同事新买的移动硬盘&#xff0c;插在电脑上识别不出来盘符&#xff0c;检查了一下&#xff0c;硬盘没问题应该&#xff0c;是ssk的硬盘盒M.2的SSD&#xff0c;硬盘驱动也是正常的&#xff0c;插拔了几次&#xff0c;都不识别&#xff0c;换了太电脑…

【Java】解决Java报错:OutOfMemoryError

文章目录 引言1. 错误详解2. 常见的出错场景2.1 内存泄漏2.2 大数据结构2.3 JVM内存参数配置不当 3. 解决方案3.1 内存泄漏检测与修复3.2 优化数据结构3.3 调整JVM内存参数3.4 使用弱引用 4. 预防措施4.1 定期进行内存分析4.2 合理设计数据结构4.3 使用合适的JVM内存参数4.4 优…

深度学习 - softmax交叉熵损失计算

示例代码 import torch from torch import nn# 多分类交叉熵损失&#xff0c;使用nn.CrossEntropyLoss()实现。nn.CrossEntropyLoss()softmax 损失计算 def test1():# 设置真实值: 可以是热编码后的结果也可以不进行热编码# y_true torch.tensor([[0, 1, 0], [0, 0, 1]], dt…

Mysql使用中的性能优化——批量插入的规模对比

在《Mysql使用中的性能优化——单次插入和批量插入的性能差异》中&#xff0c;我们观察到单次批量插入的数量和耗时呈指数型关系。 这个说明&#xff0c;不是单次批量插入的数量越多越好。本文我们将通过实验测试出本测试案例中最佳的单次批量插入数量。 结论 本案例中约每次…

【云岚到家】-day00-开发环境配置

文章目录 1 开发工具版本2 IDEA环境配置2.1 编码配置2.2 自动导包设置2.3 提示忽略大小写2.4 设置 Java 编译级别 3 Maven环境3.1 安装Maven3.2 配置仓库3.3 IDEA中配置maven 4 配置虚拟机4.1 导入虚拟机4.2 问题 5 配置数据库环境5.1 启动mysql容器5.2 使用MySQL客户端连接数据…

【YOLO系列】YOLOv1学习(PyTorch)原理加代码

论文网址&#xff1a;https://arxiv.org/pdf/1506.02640 训练集博客链接&#xff1a;目标检测实战篇1——数据集介绍(PASCAL VOC&#xff0c;MS COCO)-CSDN博客 代码文件&#xff1a;在我资源里&#xff0c;但是好像还在审核&#xff0c;大家可以先可以&#xff0c;如果没有的…

从 Android 恢复已删除的备份录

本文介绍了几种在 Android 上恢复丢失和删除的短信的方法。这些方法都不能保证一定成功&#xff0c;但您可能能够恢复一些短信或其中存储的文件。 首先要尝试什么 首先&#xff0c;尝试保留数据。如果你刚刚删除了信息&#xff0c;请立即将手机置于飞行模式&#xff0c;方法是…

【Linux】信号(二)

上一章节我们进行了信号产生的讲解。 本节将围绕信号保存展开&#xff0c;并会将处理部分开一个头。 目录 信号保存&#xff1a;信号的一些概念&#xff1a;关于信号保存的接口&#xff1a;sigset_t的解释&#xff1a;对应的操作接口&#xff1a;sigprocmask&#xff1a;sigp…

SwiftUI中Preference的理解与使用(ScrollView偏移量示例)

在 SwiftUI 中&#xff0c;Preference用于从视图层次结构的较深层次向上传递信息到较浅层次。这通常用于在父视图中获取子视图的属性或状态&#xff0c;而不需要使用状态管理工具如State或 ObservableObject。Preference特别用于自定义布局或组件&#xff0c;其中子视图需要向父…

Git 和 Github 的使用

补充内容&#xff1a;EasyHPC - Git入门教程【笔记】 文章目录 常用命令配置信息分支管理管理仓库 概念理解SSH 密钥HTTPS 和 SSH 的区别在本地生成 SSH key在 Github 上添加 SSH key 使用的例子同步本地仓库的修改到远程仓库拉取远程仓库的修改到本地仓库拉取远程仓库的分支并…

千益畅行:合法合规的旅游卡服务,真实可靠的旅游体验

近期&#xff0c;关于千益畅行旅游卡服务的讨论引起了广泛关注。然而&#xff0c;网络上出现了一些对其误解和质疑的声音。为了澄清事实&#xff0c;我们深入了解了千益畅行的运营模式和业务特点&#xff0c;发现它是一家合法合规的旅游卡服务提供商&#xff0c;为消费者提供真…

Eslint配置指南

1. Eslint配置指南 1.1. 安装 ESLint1.2. 生成配置文件1.3. 修改配置文件1.4. 创建 .eslintignore 文件1.5. 运行 ESLint1.6. 整合到编辑器/IDE1.7. 自动修复 2. 配置prettier 2.1. 安装依赖包2.2. .prettierrc.json添加规则2.3. .prettierignore忽略文件2.4. 保存自动格式化 3…

深度学习中2D分割

深度学习中的2D图像分割 2D图像分割是深度学习中的一个重要任务&#xff0c;旨在将图像划分为不同的区域&#xff0c;每个区域对应于图像中的不同对象或背景。该任务广泛应用于医学影像分析、自动驾驶、卫星图像分析等领域。以下是对深度学习中2D图像分割的详细介绍&#xff0…

实战 | 通过微调SegFormer改进车道检测效果(数据集 + 源码)

背景介绍 SegFormer&#xff1a;实例分割在自动驾驶汽车技术的快速发展中发挥了关键作用。对于任何在道路上行驶的车辆来说&#xff0c;车道检测都是必不可少的。车道是道路上的标记&#xff0c;有助于区分道路上可行驶区域和不可行驶区域。车道检测算法有很多种&#xff0c;每…

vue2实现将el-table表格数据导出为长图片

方法一、 el-table数据导出为长图片 将el-table数据导出为图片不是一个直接的功能&#xff0c;但可以通过以下步骤实现&#xff1a; 使用html2canvas库将表格区域转换为画布(canvas)。 使用canvas的toDataURL方法将画布导出为图片格式&#xff08;例如PNG&#xff09;。 创建…

数据结构--实验

话不多说&#xff0c;直接启动&#xff01;&#x1f44c;&#x1f923; 目录 一、线性表&#x1f60e; 1、建立链表 2、插入元素 3、删除特定位置的元素 4、输出特定元素值的位置 5、输出特定位置的元素值 6、输出整个链表 实现 二、栈和队列&#x1f618; 栈 顺序栈 …