Rust语言学习笔记(1)

基本语法

  • 变量的不变绑定用let,可变绑定用let mut,函数声明用fn。
    类型修饰采用后置语法,省略时由编译器根据上下文自行推导:
    变量绑定时用冒号指示类型,自带初值时类型修饰可省略。
    声明函数时用箭头指示返回类型,有返回值时返回类型不可省略。
    即便在同一作用域,相同的变量名也可反复绑定。
     不变绑定,常量声明可变绑定,变量声明函数(有返回值)函数(无返回值)
    Rustlet i = 10;
    let i: i32 = 10;
    let mut i = 10;
    let mut i: i32 = 10;
    fn f(n: i32) -> i32 {n + 1}
    fn f(n: i32) -> i32 {return n + 1;}
    fn f(n: i32) -> () {}
    fn f(n: i32) {}
    Swiftlet i = 10
    let i: Int = 10
    var i = 10
    var i: Int = 10
    func f(n: Int) -> Int {return n + 1}func f(n: Int) -> () {}
    func f(n: Int) -> Void {}
    func f(n: Int) {}
    C++const auto i = 10;
    const int i = 10;
    constexpr auto i = 10;
    constexpr int i = 10;
    auto i = 10;
    int i = 10;
    int f(int n) {return n + 1;}
    auto f(int n) -> int {return n + 1;}
    auto f(int n) {return n + 1;}
    void f(int n) {}
    auto f(int n) -> void {}
    auto f(int n) {}
  • 以不带分号的表达式结尾的代码块返回表达式的值。
    以带分号的语句结尾的代码块返回 ()。
  • 数据结构方面,数组和元组有特殊语法。数组用中括号,元组用小括号。
    // 数组
    // 由20个0组成的数组,数组类型为长度20的整型数组
    let a = [0; 20]; // a: [i32; 20]
    // 由1,2,3组成的数组
    let a = [1, 2, 3]; // a: [i32; 3]
    // 可变数组
    let mut a = [1, 2, 3]; // a: [i32; 3]
    let m = a[1];
    // 数组切片,类型为引用
    let complete = &a[..];
    let middle = &a[1..4];
    // 元组
    let x = (1, "hello"); // x: (i32, &str)
    let mut x = (1, 2); // x: (i32, i32)
    // 通过模式匹配读取元组的元素
    let (x, y, z) = (1, 2, 3);
    

所有权(ownership)

  • 在变量绑定时Rust语言缺省执行的操作为资源所有权的转移,也就是移动语义。
  • 而基本类型以及其他实现了Copy特性的类型所执行的操作则为拷贝语义。
// 移动语义
let v = vec![1, 2, 3];
let v2 = v;
// 此时v所拥有的资源已经转移给了v2,再次引用v将会报错

// 拷贝语义
let v = 1;
let v2 = v;
// 基本类型赋值时执行完全拷贝,所以v和v2都等于1

借用(borrowing)

  • 借助于 & 操作符在变量绑定时可实现资源的借用。借用的结果是引用。引用失效时借用结束。
  • 借用期间源对象(资源所有权的拥有者)不可变。引用的生命期必须短于源对象。
  • 引用可分为不变引用(不变借用的结果)和可变引用(可变借用的结果)。
  • 不变绑定以及可变绑定均可进行不变借用,但只有可变绑定才能进行可变借用。
  • 在同一作用域内对于同一变量:不变借用可多次进行,可变借用最多只能有一次,可变借用与不变借用不能同时进行。
// 不变绑定x经过不变借用得到不变引用y
let x = 5;
let y = &x;
// let y: &i32 = &x;

// 可变绑定x经过可变借用得到可变引用y
let mut x = 5;
let y = &mut x;
// let y: &mut i32 = &mut x;
// let ref mut y = x;
*y += 1;

分支(branch)与循环(loop)

// if分支
let x = 5;
if x == 5 {
    println!("x is five!");
} else if x == 6 {
    println!("x is six!");
} else {
    println!("x is not five or six :(");
}
let y = if x == 5 { 10 } else { 15 }; // y: i32
// loop循环
loop {
    println!("Loop forever!");
}
// while循环
let mut done = false; // mut done: bool
while !done {
    // if .. { done = true; }
}
// for循环
for x in 0..10 { 
    println!("{}", x); // x: i32
}
for (i,j) in (5..10).enumerate() {
    println!("i = {} and j = {}", i, j);
}
let lines = "hello\nworld".lines();
for (linenumber, line) in lines.enumerate() {
    println!("{}: {}", linenumber, line);
}
// break 与 continue
loop {
    // if .. { break; }
}
for x in 0..10 {
    if x % 2 == 0 { continue; }
}
// 循环的标号
'outer: for x in 0..10 {
    'inner: for y in 0..10 {
        if x % 2 == 0 { continue 'outer; } // continues the loop over x
        if y % 2 == 0 { continue 'inner; } // continues the loop over y
        println!("x: {}, y: {}", x, y);
    }
}

函数(functions)

  • 函数参数的传递方式与变量的绑定方式相同,即参数传递时存在拷贝,移动,不变借用,可变借用,模式匹配等方式。
    参数传递方式被调用方调用方
    拷贝fn f(x: i32) {
     print!("{}", x);
    }
    let a = 4;
    f(a);
    // 4
    移动fn f(x: Vec<i32>) {
     print!("{}", x[0]);
    }
    let v = vec![1, 2, 3];
    f(v);
    // 1
    不变借用fn f(x: &i32) {
     print!("{}", x);
    }
    let a = 4;
    f(&a);
    // 4
    可变借用fn f(x: &mut i32) {
     *x += 1; print!("{}", x);
    }
    let mut a = 4;
    f(&mut a);
    // 5
    模式匹配fn f((x, y): (i32, i32)) {
     print!("{},{}", x, y);
    }
    let a = (1, 2);
    f(a);
    // 1,2
  • 函数是一等公民。可以作为函数的参数,也可以成为函数的返回值。
  • 函数可以嵌套。

闭包(closures)

  • 闭包的参数以及返回值的类型可以省略。
    let add_one = |x| x+1;
    let add_one = |x: i32| x+1;
    let add_one = |x: i32| -> i32 {x+1};
    print!("{}", add_one(1)); // 2
    
  • 闭包可以通过拷贝,移动,不变借用,可变借用等方式捕获环境变量
    // 拷贝捕获
    let mut num = 5;
    let mut add_num = move |x: i32| {num += x; num};
    print!("{}", add_num(1)); // 6
    print!("{}", num); // 5
    // 移动捕获
    let nums = vec![1, 2, 3];
    let takes_nums = || nums;
    let takes_nums = move || nums;
    println!("{:?}", takes_nums()); // [1, 2, 3]
    println!("{:?}", nums); // error
    // 不变借用捕获
    let mut num = 5;
    let plus_num = |x| x + num;
    let x = &mut num; // error
    print!("{},{}", plus_num(1), num); // 6,5
    // 可变借用捕获
    let mut num = 5;
    {
    let mut add_num = |x: i32| {num += x; num};
    print!("{}", add_num(1)); // 6
    print!("{}", num); // error
    }
    print!("{}", num); // 6
    

参考链接

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值