入坑Rust记(1)

先上学习链接 Rust语言圣经

变量定义

Rust的赋值称为变量绑定,对于rust来说,所有的内存都是有主人的,而且一般情况下完全属于它的主人。

let x = 1; ///<将1绑定到x上

在rust中变量默认是不可变的,除非你使用mut 关键字人变量变为可变的。这看起来和常量很像,但还是有所不同,常量在编译完成后以及确定了它的值,它是自始至终不可改变的。

const MAX_POINTS: u32 = 100_000; ///常量
let x = 5;    ///<不可变变量
let mut y = 4; ///<可变变量

可以通过使用下划线开头忽略未使用的变量,这样编译器就不会产生警告。

fn main() {
    let _x = 5;
    let y = 10;
}

rust允许声明相同的变量,在后面声明的变量会遮蔽掉前面的。

fn main() {
    let x = 5;
    // 在main函数的作用域内对之前的x进行遮蔽
    let x = x + 1;

    {
        // 在当前的花括号作用域内,对之前的x进行遮蔽
        let x = x * 2;
        println!("The value of x in the inner scope is: {}", x);
    }

    println!("The value of x is: {}", x);
}

类型介绍

Rust 每个值都有其确切的数据类型,总的来说可以分为两类:基本类型和复合类型

基本类型一般有以下几部分

  • 数值: i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64
  • 字符串: 字面量和切片
  • 布尔类型: true和fasle
  • 字符类型:表示单个Unicode字符,存储为4个字节
  • 单元类型:()

Rust会根据上下文自动推导变量类型,但是当无法推导时需要手动给一个类型标注

//let guess = "42".parse().expect("Not a number!");
let guess: i32 = "42".parse.expect("Not a number!");
let guess = "42".parse::<i32>().expect("Not a number!");

数值类型

数值类型的定义和其他语言没什么不同,isize和usize分别取决于计算机的CPU类型。

与其他语言不同的是当出现整型溢出的时候,在debug模型下Rust会抱错,但是当使用--release编译时,rust不会抱错。对于这一部分处理可以通过显式的处理方式处理可能的溢出。

  • 使用 wrapping_* 方法在所有模式下都按照补码循环溢出规则处理,例如 wrapping_add
  • 如果使用 checked_* 方法时发生溢出,则返回 None 值
  • 使用 overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值
  • 使用 saturating_* 方法使值达到最小值或最大值
fn main(){
    let a: u8 = 255;
    let b = a.wrapping_add(20);
    println!("{}", b);
}

由于浮点数的底层格式的特殊性,我们应该尽量避免两个浮点数相等的比较,同时Rust的HashMap数据结构无法使用浮点数作为key值。

来看一段崩溃的代码

fn main() {
  // 断言0.1 + 0.2与0.3相等
  assert!(0.1 + 0.2 == 0.3);
}

因为二进制进度的问题,0.1 + 0.2 并不严格等于0.3,我们可以使用类似的方式来替换以上代码实现一个浮点的相等比较

fn main {
    assert!((0.1_f64 + 0.2 - 0.3).abs() < 0.000001);
}

对于数学上未定义的结果Rust会产生一个NaN, 可以通过is_nan()等方法来判断一个数值是否是NaN:

fn main() {
    let x = (-42.0_f32).sqrt();
    if x.is_nan() {
        println!("未定义的数学行为")
    }
}

在rust中,对应较长的字符可以用_进行分割,提升可读性。

let one_million: i64 = 1_000_000;

Rust可以通过1...5的方式生成从1到4的连续数字,使用1...=5的方式生产1到5的连续数字

for i in 1..=5 {
    println!("{}",i);
}

在这里推荐一个社区开发的高质量数值库:num

use num::complex::Complex;

 fn main() {
   let a = Complex { re: 2.1, im: -1.2 };
   let b = Complex::new(11.1, 22.2);
   let result = a + b;

   println!("{} + {}i", result.re, result.im)
 }

字符、布尔、单元类型

在rust中,字符为4字节编码的unicode,bool和其他语言一样只有true和false,单元类型()不占空间,单元类型在rust中作为很多函数的返回值。对于没有返回值的函数,在rust中有单独定义: 发散函数。

语句和表达式

Rust 的函数是由一系列语句组成,最后由一个表达式来返回值。如果函数没有返回任何值,会隐式的返回一个()。

fn add_with_extra(x: i32, y: i32) -> i32 {
    let x = x + 1; // 语句
    let y = y + 5; // 语句
    x + y // 表达式
}

所有权和借用

所有权原则

  • rust中每一个值都能被一个变量所拥有,该变量称为值的所有者
  • 一个值同时只能被一个变量所拥有
  • 当所有者离开作用域范围时,这个值将被丢弃

在rust中对于基本类型的互相赋值会通过拷贝的形式进行,而对于其他类型则通过转移所有权的方式进行。

let s1 = String::from("hello");
let s2 = s1;

在这段代码中,s1的值的所有权转移到了s2上,s1不再有效,既s1被移动到了s2中。而如果想要s2不被释放,需要使用深拷贝的方式将数据拷贝到s1上,可以通过clone方法来实现

let s1 = String::from("hello");
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);

在rust中有一个copy的特征,如果一个类型拥有copy特性,一个旧的变量在被赋值给其他变量后仍然可用。以下是一些具有copy特性的类型

  • 所有整数类型,比如 u32
  • 布尔类型,bool,它的值是 true 和 false
  • 所有浮点数类型,比如 f64
  • 字符类型,char
  • 元组,当且仅当其包含的类型也都是 Copy 的时候。比如,(i32, i32) 是 Copy 的,但 (i32, String) 就不是
  • 不可变引用 &T ,例如转移所有权中的最后一个例子,但是注意: 可变引用 &mut T 是不可以 Copy的

将值传递给函数一样会发生移动或者赋值,同let语句一样。

使用某个变量的指针或者引用,再Rust中通过借用这个概念来完成。

fn main() {
    let x = 5;
    let y = &x;

    assert_eq!(5, x);
    assert_eq!(5, *y);
}

上述代码使用&运算符来借用了x的值,使用*来解出借用的值。

但是正如默认不可变一样,引用指向的值默认也是不可变的,如果要改变引用的值,需要用到可变引用。

fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}
/*
let mut s = String::from("hello");

let r1 = &mut s;
let r2 = &mut s; ///<这里会报错,在rust中同一个作用域,特定数据只能有一个可变引用
println!("{}",r1); ///<如果把这行注释掉就不会报错,编译器会在引用最后一次使用的地方把它释放掉
*/

总结

通过以上我们了解了rust的一些基本规则:变量的定义、变量类型、语句和表达式、所有权和借用。后面将学习一些高级数据结构的使用方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值