2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Hello everyone
Today, the fourth session of the 2024 Autonomous Driving OS Development Training Camp - Beginner Camp - Guided Learning was completed
Day 2: Practice Rust language with rustlings - Move Semantics
https://doc.rust-lang.org/stable/book/ch04-00-understanding-ownership.html
How to solve the problem of no permission when submitting code
aciton
Reference development environment configuration
https://rcore-os.cn/arceos-tutorial-book/ch01-02.html
My topic
https://github.com/cicvedu/rustlings-semester-4-watchpoints
Create an ssh key for cloning github code via ssh. In Linux environment, use the command ssh-keygen -t rsa -b 4096 -C "your email" to create an ssh key. Just press Enter for all the options below. Then use cat ~/.ssh/id_rsa.pub
Rust has a couple of basic types that are directly implemented into the compiler. In this section, we'll go through the most important ones.
The Slice Type Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection.
A slice is a kind of reference, so it does not have ownership.
In Rust, a slice is a view of a contiguous range of elements from an array or another slice. To create a slice, you specify the start and end position of the slice (not including the end index). a
If you want to get[2, 3, 4]
For this slice, you need to start from index 1 and end at index 4 (excluding index 4).
Here's how to fix your test code:
#[test]
fn slice_out_of_array() {
let a = [1, 2, 3, 4, 5];
// 从索引 1 开始,到索引 4 结束的切片
let nice_slice = &a[1..4];
assert_eq!([2, 3, 4], nice_slice);
}
In this example,&a[1..4]
Created aa
The slice starts at index 1 and ends at index 3, because Rust's slice syntax is a left-closed and right-open interval (including the start but not the end).nice_slice
It contains the arraya
middle[2, 3, 4]
。
Type rustlings watch in the command line to start the code editing loop experiment
Understanding Ownership
Ownership is Rust’s most unique feature and has deep implications for the rest of the language.
It enables Rust to make memory safety guarantees without needing a garbage collecto
What Is Ownership?
Ownership Rules First, let’s take a look at the ownership rules. Keep these rules in mind as we work through the examples that illustrate them:
The code example itself is correct and demonstrates the concepts of ownership and copying in Rust. However, if you want to make sure your code compiles and runs, and want to address some possible improvements or corrections, here are some suggestions:
make sure takes_ownership
andmakes_copy
Function inmain
Function defined before, because functions in Rust need to be declared before they can be used.
add notes, explain why s
existtakes_ownership
After calling, it cannot be used.x
existmakes_copy
It can still be used after being called.
Add to main
Function return type, although this is not necessary in simple programs, it is good programming practice.
Using Rust's formatter,for example rustfmt
, to keep the code clean.
Here is the modified code according to the above suggestions:
fn takes_ownership(some_string: String) { // 函数定义在 main 之前
println!("{}", some_string);
} // some_string 的作用域结束,调用 Drop
fn makes_copy(some_integer: i32) { // 函数定义在 main 之前
println!("{}", some_integer);
} // some_integer 的作用域结束,没有调用 Drop,因为 i32 是 Copy 类型
fn main() -> () { // 明确 main 函数的返回类型为 ()
let s = String::from("hello"); // s 拥有 "hello" 的所有权
takes_ownership(s); // s 的值移动到 takes_ownership 函数
// 下面的代码尝试使用 s 将会导致编译错误,因为 s 的值已经移动
// let len = s.len(); // 错误:s 已移动
let x = 5; // x 包含值 5
makes_copy(x); // x 的值被复制到 makes_copy 函数
// x 仍然有效,因为 i32 是 Copy 类型
// x 仍然可以使用
println!("x is {}", x);
}
In this revised version, we added main
Function return type()
,this means main
The function does not return any value. Also, a comment is added to explain whys
existtakes_ownership
After calling, it cannot be used.x
existmakes_copy
In addition, we also show that we try totakes_ownership
Use after callings
will result in a compilation error, andx
existmakes_copy
The example can still be used after calling.
Vectors are one of the most-used Rust data structures.
In other programminglanguages, they'd simply be called Arrays, but since Rust operates on a bit of a lower level, an array in Rust is stored on the stack (meaning it can't grow or shrink, and the size needs to be known at compile time), and a Vector is stored in the heap (where these restrictions do not apply).
Vectors are a bit of a later chapter in the book, but we think that they're useful enough to talk about them a bit earlier. We shall be talking about the other useful data structure, hash maps, later.
vec_map
The function accepts aVec<i32>
type (i.e. a vector of 32-bit integers), and then returns a newVec<i32>
, each element in this new vector is twice the corresponding element in the original vector.
Specifically,vec_map
In the functionmap
andcollect
This is how the method works:
**v.iter()
**: This method creates an iterator that traverses v
Each element of the vector.iter
The iterator returned by the method provides an immutable reference to the elements in the vector.
**.map(|element| { element * 2 })
**:map
The method accepts a closure (anonymous function), in this case, the closure accepts a single parameterelement
(an immutable reference to an element in the vector), and then returns the result of multiplying the value of this element by 2. Operations within the closure element * 2
In fact, it is dereferencing the data pointed to by the reference (through*
operator) and perform a multiplication operation.
**.collect()
**:map
The method returns a lazy iterator that applies the operations in the closure one by one but does not collect the results immediately.collect
method is called to pass thesemap
The processed elements are collected into a newVec<i32>
Vector.
use map
andcollect
The benefit of is that they allow you to perform operations on each element in a collection in a declarative way and collect the results into a new collection without having to write explicit loops. This makes the code more concise and more in line with the Rust style.
Here is a tutorial on how to use vec_map
Example of a function:
fn main() {
let original_vec = vec![1, 2, 3, 4];
let doubled_vec = vec_map(&original_vec);
println!("{:?}", doubled_vec); // 这将打印:[2, 4, 6, 8]
}
In this example,vec_map
take overoriginal_vec
A new vector is created by usingdoubled_vec
, which contains twice the value of each element of the original vector, and prints it out.
These exercises are adapted from pnkfelix's Rust Tutorial -- Thank you Felix!!!
For this section, the book links are especially important.
Mutable references in Rust have a rule: you can have any number of immutable references or at most one mutable reference at any given time. This rule ensures memory safety and prevents data races.
In the code provided, there is a problem:main
Function attempts to create two mutable referencesy
andz
, both refer to the same variable x
. This is not allowed because Rust's borrowing rules do not allow multiple mutable references to the same variable in the same scope. That's why the code does not compile.
To fix this, you need to ensure that only one mutable reference exists at any given time. Here is the fixed code:
fn main() {
let mut x = 100;
{
let y = &mut x;
*y += 100; // 此时 x 的值变为 200
} // 'y' 的作用域结束,可变引用被销毁
{
let z = &mut x; // 可以创建新的可变引用,因为 'y' 已经不存在了
*z += 1000; // 此时 x 的值变为 1200
} // 'z' 的作用域结束,可变引用被销毁
assert_eq!(x, 1200); // 断言 x 的值是 1200,这是正确的
}
In this fixed version, we create an inner scope to ensure that only one mutable reference exists at any time. First, we create y
, operates on it, and then the scope ends.y
is no longer valid. After that, we createdz
Scope, againx
This obeys Rust's borrowing rules, allowing the code to compile and run as expected.
This compilation error message points out a lifetime problem in Rust code. The problem is string_uppercase
In the implementation of the function, it attempts to assign a temporary value to a reference, which is not allowed.
Here is the line of code where the error occurs:
data = &data.to_uppercase();
In this line of code,data.to_uppercase()
Created aString
A new instance of this instance is a temporary value, and its life cycle depends ondata
However, an attempt is made to assign a reference to this temporary value todata
is illegal because the temporary value is destroyed as soon as the statement ends, anddata
Need a lifetime longer than a temporary value.
To fix this problem, we need to modify string_uppercase
function, so that it accepts a mutable reference and calls it directly on the data pointed to by the referencemake_uppercase()
method instead of trying to reassign the value. Here is the fixed code:
fn string_uppercase(data: &mut String) {
data.make_uppercase(); // 直接在 data 上调用 make_uppercase 方法
println!("{}", data);
}
In this fix release, we removed mut data: &String
middlemut
,because data
is already a mutable reference. Then we directlydata
Callmake_uppercase()
, so there won't be any problem with temporary values.make_uppercase()
The method will be modifieddata
ReferencedString
Instances without creating newString
。
also,main
The call to the function also needs to be updated accordingly to pass a mutable reference:
fn main() {
let mut data = "Rust is great!".to_string();
string_uppercase(&mut data); // 传递一个可变引用
println!("{}", data); // 打印修改后的字符串
}
Now,string_uppercase
Function Acceptdata
a mutable reference to , modifying it directly, andmain
In the functiondata
is mutable and can bestring_uppercase
This way the code compiles and works as expected.
/**
【昵称】小王同学
【坐标】山东
【自我介绍】
1. 高级后端工程师,擅长c++并发编程。
2. 专注分布式存储,分布式数据库。
3. 时间的践行者,立志成为一名讲师。
【我的成绩】
1. 为了走出农村,2次高考
一次考研失败,
遇挫之后不知道干什么,开启被动之旅。
2. 为了找到合适工作,
深入研究c++书籍和leetcode 200题目
3. 为了提高项目能力,参与开源项目建设。
4. 为了把简单事情说清楚/要干啥
按照《只管去做》,《福格行为模型>>方法。
纸上得来终觉浅,绝知此事要躬行
做一个践行者。
【我能提供】
1. 后端程序员的简历优化+就业辅导+职业规划
2. 全栈工程师(c++,rust,go,python )项目开发
3. 一年践行12本书践行记录。
【希望一起解决什么,开启破圈之旅】
1. 交接更多朋友,抱团取暖。
寻找意义本身就更加有意义。
2. 无法做整个系统,聚焦一个模块
道可道也,非恒道也
名可名也,非恒名也。
无名 万物之始也
有名 万物之母也
别想太多,只管去做,躬身入局
链接我: # + v(github):watchpoints
#众号:后端开发成长指南
**/
This article is provided by mdnice Multi-platform release