Rust从入门到实战系列三百:所有权

本文讨论了Rust中的类型转换策略,包括Copy特性、所有权转移,以及如何在SipHash性能不足时选择社区库。还介绍了数值溢出处理、无符号整型转换技巧,以及裸指针和内存地址的处理。
摘要由CSDN通过智能技术生成

对于实现了 Copy 特征的类型,例如 i32 ,那类型的值会被拷贝到 HashMap 中。而对于有所有权的类
型,例如 String ,它们的值的所有权将被转移到 HashMap 中。
5. 🌟🌟
// 修 复 错 误 , 尽 可 能 少 的 去 修 改 代 码
// 不 要 移 除 任 何 代 码 行 !
use std::collections::HashMap;
fn main() {
let v1 = 10;
let mut m1 = HashMap::new();
m1.insert(v1, v1);
println!(“v1 is still usable after inserting to hashmap : {}”, v1);
let v2 = “hello”.to_string();
let mut m2 = HashMap::new();
// 所 有 权 在 这 里 发 生 了 转 移
m2.insert(v2, v1);
assert_eq!(v2, “hello”);
println!(“Success!”)
}
三方库 Hash 库
在开头,我们提到过如果现有的 SipHash 1-3 的性能无法满足你的需求,那么可以使用社区提供的替代算
法。
例如其中一个社区库的使用方式如下:
use std:#️⃣:BuildHasherDefault;
use std::collections::HashMap;
// 引入第三方的哈希函数
use twox_hash::XxHash64;
let mut hash: HashMap<_, _, BuildHasherDefault> = Default::default();
hash.insert(42, “the answer”);
assert_eq!(hash.get(&42), Some(&“the answer”));
Type conversions
There are several ways we can use to perform type conversions, such as as , From/Intro ,
TryFrom/TryInto , transmute etc.
使用 as 进行类型转换
Rust 并没有为基本类型提供隐式的类型转换( coercion ),但是我们可以通过 as 来进行显式地转换。

  1. 🌟
    // 修 复 错 误 , 填 空
    // 不 要 移 除 任 何 代 码
    fn main() {
    let decimal = 97.123_f32;
    let integer: __ = decimal as u8;
    let c1: char = decimal as char;
    let c2 = integer as char;
    assert_eq!(integer, ‘b’ as u8);
    println!(“Success!”)
    }
  2. 🌟🌟 默认情况下, 数值溢出会导致编译错误,但是我们可以通过添加一行全局注解的方式来避免编
    译错误(溢出还是会发生)
    fn main() {
    assert_eq!(u8::MAX, 255);
    // 如 上 所 示 ,u8 类 型 允 许 的 最 大 值 是 255.
    // 因 此 以 下 代 码 会 报 溢 出 的 错 误 : literal out of range for u8.
    // 请 仔 细 查 看 相 应 的 编 译 错 误 , 从 中 寻 找 到 解 决 的 办 法
    // 不 要 修 改 main 中 的 任 何 代 码
    let v = 1000 as u8;
    println!(“Success!”)
    }
  3. 🌟🌟 当将任何数值转换成无符号整型 T 时,如果当前的数值不在新类型的范围内,我们可以对当
    前数值进行加值或减值操作( 增加或减少 T::MAX + 1 ),直到最新的值在新类型的范围内,假设我们
    要将 300 转成 u8 类型,由于 u8 最大值是 255,因此 300 不在新类型的范围内并且大于新类型的
    最大值,因此我们需要减去 T::MAX + 1 ,也就是 300 - 256 = 44 。
    fn main() {
    assert_eq!(1000 as u16, __);
    assert_eq!(1000 as u8, __);
    // 事 实 上 , 之 前 说 的 规 则 对 于 正 整 数 而 言 , 就 是 如 下 的 取 模
    println!(“1000 mod 256 is : {}”, 1000 % 256);
    assert_eq!(-1_i8 as u8, __);
    // 从 Rust 1.45 开 始 , 当 浮 点 数 超 出 目 标 整 数 的 范 围 时 , 转 化 会 直 接 取 正 整 数 取 值 范 围 的 最 大 或
    assert_eq!(300.1_f32 as u8, __);
    assert_eq!(-100.1_f32 as u8, __);
    // 上 面 的 浮 点 数 转 换 有 一 点 性 能 损 耗 , 如 果 大 家 对 于 某 段 代 码 有 极 致 的 性 能 要 求 ,
    // 可 以 考 虑 下 面 的 方 法 , 但 是 这 些 方 法 的 结 果 可 能 会 溢 出 并 且 返 回 一 些 无 意 义 的 值
    // 总 之 , 请 小 心 使 用
    unsafe {
    // 300.0 is 44
    println!(“300.0 is {}”, 300.0_f32.to_int_unchecked::());
    // -100.0 as u8 is 156
    println!(“-100.0 as u8 is {}”, (-100.0_f32).to_int_unchecked::());
    // nan as u8 is 0
    println!(“nan as u8 is {}”, f32::NAN.to_int_unchecked::());
    }
    }
  4. 🌟🌟🌟 裸指针可以和代表内存地址的整数互相转换
    // 填 空
    fn main() {
    let mut values: [i32; 2] = [1, 2];
    let p1: *mut i32 = values.as_mut_ptr();
    let first_address: usize = p1 __;
    let second_address = first_address + 4; // 4 == std::mem::size_of::()
    let p2: *mut i32 = second_address __; // p2 指 向 values 数 组 中 的 第 二 个 元 素
    unsafe {
    // 将 第 二 个 元 素 加 1
    __
    }
    assert_eq!(values[1], 3);
    println!(“Success!”)
    }
  5. 🌟🌟🌟
    fn main() {
    let arr :[u64; 13] = [0; 13];
    assert_eq!(std::mem::size_of_val(&arr), 8 * 13);
    let a: *const [u64] = &arr;
    let b = a as *const [u8];
    unsafe {
    assert_eq!(std::mem::size_of_val(&*b), __)
    }
    }
  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值