- 常量用const,,一般是用大写字母命名如:
const MAX_POINTS: u32 = 100_000;
- 变量用mut
- Shadowing(隐藏):可以使用相同变量名
- Rust是静态编译语言,在编译时必须知道每个变量的类型
- 有符号整数类型以i开头(有负有正),无符号整数类型以u开头(非负),有符号范围:-(2^n-1)~(2^(n-1)-1),无符号范围:0~2^n-1
- 溢出时调试模式会恐慌,发布模式不会,而是环绕。
- tuple里的类型是不可变的:
fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tup;
println!("{}, {}, {}", x, y, z)
}
- 数组里的类型必须相同,长度固定,可以将多个值放在一个类型里,用中括号,逗号分开。
- 数组没有Vector灵活
let a = [3;5]相当于let a = [3, 3, 3, 3, 3];
- 函数参数类型必须指明。
- 函数的返回值:
在->符号后便声明函数返回值的类型,但是不可以为返回值命名
在Rust里面,返回值就是函数体里面最后一个表达式的值
若想提前返回,须使用return关键字,并指定一个值
大多数函数都是默认使用最后一个表达式作为返回值
- 但如果使用了多于一个else if,那么最好使用match来重构代码。
- 所有权:Rust的核心特征——内存是通过一个所有权来管理的,其中包含一组编译器在编译时检查的规则,当程序运行时,所有权的特性不会减慢程序的运行速度。
- Stack Vs Heap(栈内存vs堆内存)
- Stack:后进先出,添加数据叫做压入栈,移除数据叫弹出栈;所有存储在stack上的数据必须拥有已知的固定的大小;编译是大小未知的数据进行运行时大小可能发生变化的数据必须存放在heap上。
- Heap内存组织性差一些:当你把数据放入Heap时,你会请求一定数量的空间。
- 把数据压在stack上要比在heap上分配快得多。
- Rust采用了不同的方式:对于某个值来说,当拥有它的变量走出作用范围时,内存会立即自动的交还给操作系统。
- 多个变量可以与同一个数据使用一种独特的方式来交互
- let x = 5;
- let y = x;
- 整数是已知且固定大小的简单的值,这两个5被压到了栈中;
- 变量赋值给另一个变量后就失效了,不能再用这个变量了!这个术语:Move;
- Rust不会自动创建深度拷贝;除非使用克隆(针对Heap,消耗资源):
fn test6() {
let s1 = String::from("Hello");
let s2 = s1.clone();
println!("{}, {}", s1, s2);
}
- Stack上的数据:复制。一些拥有Copytrait的类型:
一些简单标量的组合类型都是可以Copy的,字符串String算是复杂类型,所以不能Copy.
任何需要分配内存或某种资源的都不是Copy的。
一些拥有Copy trait的类型:
所有的整数类型,例如u32
bool
char
所有的浮点类型,例如f64
tuple,如果其所有的字段都是Copy的
- 函数在返回值的过程中同样也会发生所有权的转移
- 可使用元组的形式复制之前的值
- 引用(&):允许你引用某些值而不取得其所有权 。
- 借用:我们把引用作为函数参数这个行为叫做借用。不可以修改借用的东西,但是可变引用(&mut),只能存在一个,不能是多个!防止数据竞争。
- 可以通过创建新的作用域,来允许非同时的创建多个可变引用:
- 不可以同时拥有一个可变引用和一个不变的引用,多个不变的引用是可以的。
- 悬空引用Dangling References:一个指针引用了内存中的某个地址,而这块内存可能已经释放并分配给其他人使用了。Rust里,不会出现这个情况。
- 引用的规则
- 一个可变的引用
- 任意数量不可变的引用
- 引用必须一直有效
- 切片:Rust的另一种不持有所有权的数据类型:切片(slice)。形式:[开始索引..结束索引],前闭后开的形式,例:
fn main() {
println!("Hello world!");
another_function();
let y = {
let x = 1;
x + 3
};
println!("The value is {}", y);
let x = plus_five(6);
println!("The value is {}", x);
test1();
test2();
test3();
test4();
test5();
test6();
let my_string = String::from("Hello World!");
let world_index = first_world(&my_string[..]);
println!("{}", world_index);
}
fn another_function() {
println!("another function!");
}
fn plus_five(x: i32) -> i32 {
x + 5
}
fn test1() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is : {}", number)
}
fn test2() {
let mut counter = 0;
let results = loop {
counter += 1;
println!("The counter is {}", counter);
if counter == 10 {
break counter * 2;
};
};
println!("The result is: {}", results)
}
fn test3() {
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("The value is {}", element);
}
}
fn test4() {
for number in (1..4).rev() {
println!("{}", number);
};
println!("LiftOff");
}
fn test5() {
let mut s = String::from("Hello");
s.push_str(", World!");
println!("{}", s)
}
fn test6() {
let s1 = String::from("Hello");
let s2 = s1.clone();
println!("{}, {}", s1, s2);
}
fn first_world(s: &str) -> &str {
// str:字符串字面值
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return &s[..i];
}
}
&s[..]
}
第一天结束!