Rust compared with other languages

features

The ownership of

In Rust, if you declare a variable similar to the concept of reference-passing type in Java or C++ and assign an address to another variable in the same scope, ownership of that variable is transferred and the original variable becomes inaccessible.

Direct transfer

/* Error: If the address is acquired by a new variable, it will lose ownership. * /
fn test2() {
    let a:Vec<i32> = Vec::new();
    a.push(1);
    let b = a; // Transfer ownership of A to B
    println!("{}", a[0]); // Try to access variable A that has lost ownership
}
​
Copy the code

Indirect transfer


/* Error: the address of the _v variable is assigned to the change argument v, and ownership has been transferred */
fn test3() {
    let _v:Vec<i32> = Vec::new();
    _v.push(1);
    /* The change function takes ownership of the passed Vec instance */
    let change = |v:Vec<i32> | - > () {return;
    };
    change(_v);
    println!("{}", _v[0]); // Try to access the variable _v that has lost ownership
}
Copy the code

Quote, borrow

In Rust, because of the property of ownership, if you want to do something with another variable to read its value without losing its ownership, you can use the reference property by prefixing the variable name with &.

In fact, this scenario is quite common.

Let nums:Vec

= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].to_vec(); , we need to obtain the results of their accumulation and multiplication respectively. In order not to lose ownership, iterating directly using NUMS variables to get results is obviously feasible, but not elegant. We can respectively implement accumulative, accumulative functions to operate.

Fn sum(arr: Vec

)->i32, fn mult(arr: Vec

)->i32.

But this can cause a problem: indirect migration of test3 code snippets does. When the _v variable is passed as an argument to the change function, ownership of _v has been transferred to the parameter v of the change function. This means that once change is executed, _v has lost ownership and is not accessible.

In this case, fn sum(arr: Vec

) and fn mult(arr: Vec

) are the signature of the function, which means that we can only execute one sum or mult at most, because the ownership of NUMS will be transferred when executing one of them.

So in order to keep its original ownership, we need a way to borrow it, and that way is by reference. For accumulation and multiplication, we can write code like this.

fn sum(arr: &Vec<i32- > >)i32 {
    let mut ans = 0;
    for n in arr.iter() {
        ans += n;
    }
    ans
}
fn mult(arr: &Vec<i32- > >)i32 {
    let mut ans = 1;
    for n in arr.iter() {
        ans *= n;
    }
    ans
}
let nums:Vec<i32> = [1.2.3.4.5.6.7.8.9.10].to_vec();
let ans1 = sum(&nums); // Pass nums by reference to ensure that NUMs does not lose ownership, similarly below
let ans2 = mult(&nums);
println!("sum:{} mult:{}", ans1, ans2);
Copy the code

Variability and immutability

The let keyword of Rust is inherently const, but has a slightly different effect than the const keyword of JavaScript or C++. Const variables decorated in JavaScript and C++ are used to ensure that the address of the heap to which the variable points has changed, regardless of whether the address to the memory in the heap has changed.

The following code snippets are legal in TypeScript.

const array: Array<int> = []; // Declare an array named array of type int
array.push(1); // Add element 1 to array
Copy the code

The following code snippet is legal in C++.

const vector<int> array = vector<int> ();// Declare an array named array of type int
array.push_back(1); // Add element 1 to array
Copy the code

Rust, on the other hand, does not. Any variable, unmodified by the MUT keyword, is immutable, whether it is memory in the stack or memory in the heap.

/* Error: cannot borrow `array` as mutable, as it is not declared as mutable */
let array:Vec<i32> = Vec::new(); // Declare a name named
array.push(1); // Try to add element 1 to array
Copy the code

If you want to add elements to it, you must use the MUT keyword.

/* Unlike javascript const, Rust cannot change the data in a container if it does not specify a muT. * /
fn test5() {
    let mut _v:Vec<i32> = Vec::new();
    _v.push(1); // Add it directly
    /* The change function gets the right to borrow the passed Vec instance */
    let change = |v:& mut Vec<i32>| -> () {
        v.push(3);
        return;
    };
    change(&mut _v);
    println!("{}", _v[1]); // The element 3 added by the change function can be successfully obtained
}
Copy the code