EX01
- change the
printline!toprintln!
the println! can print sth with \n,but print! can't
EX02
- add
letin front of thex
1.the variable declare by the let is read-only except of adding mut
2.let can automatically infer the type of the variable
EX03
好吧,我博客的富文本显示器甚至不支持
rust的代码块fn main() { // TODO: Change the line below to fix the compiler error. let x; if x == 10 { println!("x is ten!"); } else { println!("x is not ten!"); } }- assign inital value to
x
1.You absolutely can't read or use a variable before it's actually assigned.
2.But you can first declare a variable with let without giving it an initial value.
3.If you violate the principle above, the compiler will just throw an error and refuse to compile.
4.Because rust won’t assign a default value or random garbage memory to uninitialized variables
EX04
i32meansint 32, 32-bit integer, so I need to assign a corresponding value to the variable
EX05
- add
mutto make the variable variable (
EX06
fn main() {
let number = "T-H-R-E-E"; // Don't change this line
println!("Spell a number: {number}");
// TODO: Fix the compiler error by changing the line below without renaming the variable.
number = 3;
println!("Number plus two is: {}", number + 2);
}- add
letto create a brand new variable, that will shadow the former variable
Even if I add mut to line 1, that still make no sense, because you can't change the variable from one
type to another type, like from string to int
EX05
// TODO: Change the line below to fix the compiler error.
const NUMBER = 3;
fn main() {
println!("Number: {NUMBER}");
}
- add
: i32behind theNUMBER
using const to declare variable do not support the "type inference", so you must declare the type manually
EX06
- just add a function named "call_me"
EX07
- Well, leak of the type declaration, so just add
: i32
EX08
num: u8:unsigned 8-bit integer
EX10
- In a function, the last line without the end of
;is a Expression instead of a Statement, so it can act asreturn, meaning that the result of the Expression will bereturn, of course you can also usereturnlike C
EX if3
- All branch of the Expression of
if-elseneed a equal data type. - Not like Python, Rust absolutely won’t secretly convert integers to floats at runtime
EX structs1
- Just add the field of the struct to test and instantiate the
struct. - There are three type of the
struct, consist ofregular,tuple,unit.
EX structs2
- Need to use
struct upadte syntaxto instantiate the new struct.
&str is not same as String.&str is a slice of string, which was hard-code in the binary file.String is allocated to the heap, String::from("...") or "...".to_string() can be used to transfer the &str to String
EX structs3
- Finish the logic part of the function.
EX enums
- The
enumof the Rust have a far cry from Python (
Knowledge
array
- create an array
fn main() {
// Rust 会自动推导 a 的类型为 [i32; 5]
let a = [1, 2, 3, 4, 5];
// Rust 自动推导 months 为 [&str; 12]
let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
}
fn main() {
// 强制声明这是一个包含 5 个 32位整数的数组
let a: [i32; 5] = [1, 2, 3, 4, 5];
// 强制声明这是一个包含 3 个 无符号8位整数的数组
let bytes: [u8; 3] = [255, 0, 128];
}
fn main() {
// 创建一个包含 5 个 3 的数组。等价于 [3, 3, 3, 3, 3]
let a = [3; 5];
// 创建一个大小为 1024,内部全为 0 的缓冲区,这在处理底层字节流时非常常见
let buffer: [u8; 1024] = [0; 1024];
}
// 创建一个动态数组,可以随时向里面 push 新元素
let mut vec_a = vec![1, 2, 3];
vec_a.push(4);vecis allocated in heap, while others are in stack.
slice
let a = [10, 20, 30, 40, 50];
// 1. 省略起点(默认从 0 开始)
let slice1 = &a[..2]; // 等价于 &a[0..2],输出: [10, 20]
// 2. 省略终点(默认直到数组末尾)
let slice2 = &a[3..]; // 包含索引 3 及之后所有元素,输出: [40, 50]
// 3. 全切片(引用整个数组)
let slice3 = &a[..]; // 输出: [10, 20, 30, 40, 50]
// 4. 包含终点(使用 ..=)
// 如果你希望左右两边都包含,加上等号
let slice4 = &a[1..=3]; // 包含索引 1, 2, 3,输出: [20, 30, 40]- Includes the
startindex but not theendindex - the argument in
[]means theindex
切片操作会带来一个类型变化:
let a = [1, 2, 3, 4, 5];:
·a 的类型是 [i32; 5] (一个长度固定的数组,拥有这段内存的所有权)。let slice = &a[1..3];:
·slice 的类型变成了 &[i32] (一个整数切片)。
&[i32] :
它在底层是一个“胖指针(Fat Pointer)”。它本身不存储数据,而是包含了两个信息:
·指针:指向切片起始位置(即 a 数组中索引为 1 的位置)。
·长度:这个切片包含几个元素(长度为 2)。切片只是借用了原数组的数据,没有产生新的所有权,所以它的开销极小。这也意味着,只要 slice 还在被使用,Rust 的借用检查器就会保护原数组 a,不允许原数组被销毁。
Tuple Destructuring (元组解构)
let cat = ("Furry McFurson", 3.5);
let (name, age) = cat;访问元组元素
- Can't use
[],[]is exclusively for array and slice - Join the name of the Tuple and the index using
.
let numbers = (1, 2, 3);
let second = numbers.1;vec 动态数组
- Initialization:
// 方式 A:使用宏,直接给出一组初始值
let mut v1 = vec![1, 2, 3];
// 方式 B:使用宏,批量初始化相同的值 (比如创建 5 个 0)
let mut v2 = vec![0; 5];
// 方式 C:创建一个完全空的 Vec,不使用宏
// 注意:如果后面没有立刻 push 数据,编译器猜不出类型,需要显式标注
let mut v3: Vec<i32> = Vec::new();- Add:
let mut v = vec![1, 2];
// 尾部追加 (最常用,效率最高,O(1) 复杂度)
v.push(3); // 此时 v 变成 [1, 2, 3]
// 插入到指定索引 (原位置及后面的元素会自动向后移动,O(n) 复杂度)
v.insert(1, 99); // 在索引 1 的位置插入 99。此时 v 变成 [1, 99, 2, 3]- Remove:
let mut v = vec![10, 20, 30, 40];
// 弹出尾部元素 (最常用,O(1) 复杂度)
// 注意:它返回的不是具体的数字,而是一个 Option 枚举 (Some 里面包裹着值,或者 None 代表空)
let last_item = v.pop(); // last_item 是 Some(40),v 变成 [10, 20, 30]
// 移除指定索引的元素 (后面的元素会自动向前填补,O(n) 复杂度)
let removed_item = v.remove(1); // 移除索引 1 的元素。removed_item 是 20,v 变成 [10, 30]迭代器适配器配合闭包
fn vec_map_example(input: &[i32]) -> Vec<i32> {
// An example of collecting a vector after mapping.
// We map each element of the `input` slice to its value plus 1.
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
input.iter().map(|element| element + 1).collect()
}input.iter()converts the slice[1, 2, 3]into an iterator..mapcan receive the element from the iterator one by one, then|element| element + 1is闭包, like the匿名函数,.|element|define the input argument of this匿名函数,element + 1is the body of the function, and it's also its return value (note that there's no;here; this is an expression).Iterators themselves are 'lazy' (they just represent a computation process). You need an action to collect all the finished products at the end of the pipeline and assemble them into a whole new data structure.So that is what thing the.collect()do..collect()will see the-> Vec<i32>, and that decide that.collect()will return aVec
ownership
- 好吧,讲原理的问题还是用中文好点。
- 分配在栈(Stack)上的数据,Rust 采取的是拷贝语义(Copy Semantics),即不会发生所有权转交的问题。
- 分配在堆(heap)上的数据,Rust 采取的是移动语义(Move Semantics),即会发生所有权转交的问题
- 所有权问题:
// TODO: Make both vectors `vec0` and `vec1` accessible at the same time to
// fix the compiler error in the test.
#[test]
fn move_semantics2() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec0, [22, 44, 66]);
assert_eq!(vec1, [22, 44, 66, 88]);
}- Complex data structures like Vec, which are allocated on the heap, can only have one owner at a time.
When you writelet vec1 = fill_vec(vec0);something very important happens: you move the ownership ofvec0to thefill_vecfunction. Once the move is complete, the original ownervec0immediately becomes invalid (to preventDouble Free)

- 好吧,其他的东西我就记在本地了,不放上来了喵(
评论已关闭