- Published on
Rustlings-Move-Semantics
- Authors
- Name
- DP Piggy
- @xiaozhudxiaozhu
move_semantics1.rs
The fill_vec function return a mutable type of vec, so we should define a mutable type of vec to receive it.
let mut vec1 = fill_vec(vec)
fn main() {
let vec0 = Vec::new();
let mut vec1 = fill_vec(vec0);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
// This function return a mutable vec
// So should define a mutable type of vec to receive it
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec;
vec.push(22);
vec.push(44);
vec.push(66);
vec
}
move_semantics2.rs
We use clone() method to avoid any ownership issues, because we just create a copy of the vec0.
So we can perform any operations on vec0 and vec1 before or after calling the fill_vecfunction, because they are distinct objects.
fn main() {
let vec0 = Vec::new();
let mut vec1 = fill_vec(vec0.clone());
// Do not change the following line!
println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec;
vec.push(22);
vec.push(44);
vec.push(66);
vec
}
move_semantics3.rs
We defined the parameter of the function as an immutable variable, but then we tried to modify the variable by calling vec_push() method inside the function. In Rust, the Vec::new() method returns a new, empty Vec that is mutable by default and an immutable variable cannot be modified. Therefore, we should add mut before the parameter of the function.
fn main() {
let vec0 = Vec::new();
let mut vec1 = fill_vec(vec0);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> {
vec.push(22);
vec.push(44);
vec.push(66);
vec
}
move_semantics4.rs
Inside the function fill_vec(), we create a new and mutable Vec using vec![] macro, and then we can use push() method to add element to it. And we need remove the parameter of fill_vec in main function.
fn main() {
// 1. if we want to use vec0, we can give vec0 an explicit type
let vec0: Vec<i32> = Vec::new();
// 2. or use vec0.push() and vec![], just perform the vec0 to let compiler infer the type of vec0
// (1).let mut vec0 = Vec::new();
// vec0.push(1);
// (2). let mut vec0 = vec![1, 2, 3];
// 3. and delete it is ok, because in the problem we don't need it!
let mut vec1 = fill_vec();
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
// `fill_vec()` no longer takes `vec: Vec<i32>` as argument
fn fill_vec() -> Vec<i32> {
let mut vec = vec![];
vec.push(22);
vec.push(44);
vec.push(66);
vec
}
move_semantics5.rs
In Rust, if there is a mutable reference to a variable, there cannot be any other mutable or immutable references to the same variable at the same time, as this may cause data races;
fn main() {
let mut x = 100;
let y = &mut x;
*y += 100;
let z = &mut x;
*z += 1000;
assert_eq!(x, 1200);
}
move_semantics6.rs
It is important to note that the get_char function takes a &String parameter, indicating that it is borrowing a reference to the String rather than taking ownership. This means that original String object remains valid after calling get_char, because ownership has not been transferred.
But after the string_uppercase(data) call, we can not use data variable anymore because its value has been moved and release inside the function. If we need use original data variable after string_uppercase function, we can use clone() method to copy the value of data and then pass it as a function parameter to string_uppercase.
fn main() {
let data = "Rust is great!".to_string();
println!("{}", get_char(&data));
println!("{}", data);
string_uppercase(data.clone());
// string_upppercase(data);
// println!("{}", data); rust complier will report an error
println!("{}", data);
}
// Should not take ownership
fn get_char(data: &String) -> char {
data.chars().last().unwrap()
}
// Should take ownership
fn string_uppercase(mut data: String) {
data = data.to_uppercase();
println!("{}", data);
}