Ownership is the most characteristic function of trust, which can ensure the memory security without garbage collection mechanism. So what is ownership and what is the use?

First of all, ownership in trust means:
1. Ownership rules:

(1) Each value in, rust has a variable called its owner.
(2) , can only be one owner at a time.
(3) When the owner is out of scope, the value will be deleted.

2. What is the scope of actionSimilar to the scope of action:{let s = "hello";}

3. Memory and allocation:
In trust, when the variable with memory is out of range, the memory will be released automatically

fn main() {
    {
        //From now on, s is effective
        let s = String::from("hello"); 

        //Do something with S
    }
    //This scope has now ended and S is no longer valid
}

**: when the variable is out of range, rust calls a special function for us. This function, called drop, is where the creator of a string (illustrated by the example above) can place code to return to memory. Rust automatically closes the except call in the right brace.

*How variables and data interact: Mobile
Multiple variables can interact with the same data in different ways in rust. For example:

fn main() {
    let x = 5;
    let y = x;
}
//Bind the value 5 to X; then copy the value in X and bind it to y Now, we have two variables X and y, both of which are equal to 5. This is true because integers are simple values with known fixed sizes, and the five values are pushed onto the stack.

Let’s take a look at the string type

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;
}
//This looks very similar to the previous code, so we can assume that it works the same way: that is, the second line copies the value in S1 and binds it to S2. But that's not exactly what happens.

//The string consists of three parts: pointer to memory, which is used to save the content, length and capacity of the string. This set of data is stored in the stack. 

//Length is the amount of memory (in bytes) that string is currently using. Capacity is the total amount of memory (in bytes) string receives from the allocator. The difference between length and capacity is important, but not in this case, so the capacity can be ignored for the time being.

//When we assign S1 to S2, we copy the string data, which means we copy the pointer, length and capacity on the stack. We don't copy data to the heap referenced by the pointer.

//If rust replicates the heap data instead, the runtime performance S2 = S1 may be very expensive if the data on the heap is large.

//When the variable is out of range, rust automatically calls the drop function and clears the heap memory of the variable. But if there are two data pointers to the same location. This is a problem: when S2 and S1 are out of range, they will both try to free the same memory. This is called a double release error and is one of the memory security errors. Releasing memory twice may lead to memory corruption, which may lead to security vulnerabilities.

Ensure data security:
To ensure memory security, details of this situation appear in rust. Instead of trying to copy the allocated memory, rust thinks that S1 is no longer valid. Therefore, when S1 is out of range, rust does not need to release anything. Check what happens when you try to use S1 after creating S2; it doesn’t work:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;

    println!("{}, world!", s1);
}
//let s1 = String::from("hello"); 
               | -- `move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait`
 //`let s2 = s1;`
          `-- value moved here`
 //` println!("{}, world!", s1);`
                           `^^ value borrowed here after move`
               

There are the concepts of shallow copy and deep copy in JS. But because rust also invalidates the first variable, rather than being called a shallow copy, it is called a move. In this example, we say S1 has moved into S2. This is the concept of mobile in trust

This explains the above problems! Only S2 is valid. When it is out of range, it can release memory, and we are done.

Moreover, it suggests a design choice: rust will never automatically create “deep” copies of the data. Therefore, any automatic replication can be considered cheap in terms of runtime performance.

How variables interact with data: cloning
If we really want to deeply copy the heap data of string, not just the stack data, we can use a general method called clone, for example:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();

    println!("s1 = {}, s2 = {}", s1, s2);
}
//At this time, S1 still works, its value is only copied, but the storage space it points to is not copied.

Stack data only: copy
Let’s start with an example

fn main() {
    let x = 5;
    let y = x;

    println!("x = {}, y = {}", x, y);
}
//What this code reveals is:
//Types such as integers of known size at compile time are completely stored on the stack, so you can quickly make copies of actual values. This means that after creating the variable y, there is no reason to prevent x from taking effect. In other words, there is no difference between deep copy and shallow copy, so calling clone is no different from normal shallow copy, so we can omit clone operation.

Rust has a special annotation called the copy feature, which we can place on types such as integers stored on the stack. If the type has a copy feature, the older variable can still be used after assignment. If the type or any part of it implements the drop feature, rust will not allow us to annotate the type with the copy feature. If the type requires special handling when the value is out of range and a copy annotation is added to the type, a compile time error occurs.

So what’s the type of replication? As a general rule, any set of simple scalar values can be copy, and any content that does not need to be allocated or some form of resource can be copy. Here are some copy types:

*All integer types, such as U32.
*Boolean type Boolean values with true and false values.
*All floating point types, such as f64.  
*Character type, ` char '.  
*Tuples (if they contain only types that can also be copied). For example, '(I32, I32)'Is copy, but' (I32, string)'Is not.

Ownership and function:
The semantics used to pass values to functions are similar to those used to assign values to variables. Just like assignment, passing a variable to a function moves or copies it. Here is an example with some comments that show where a variable enters and goes out of scope:

fn main() {
    Let s = string:: from ("hello"); // s enters the scope

    takes_ Ownership (s); // move the value of s into the function
                                    //... so it doesn't work here or after

    Let x = 5; // X enters the scope

    makes_ Copy (x); // x will be moved into the function,
                                    //But I32 is copy, so you can use X after that

}// here, X is out of scope, followed by S. But because the value of S is shifted, nothing special happens.

fn takes_ ownership(some_ string: String) { // some_ String into scope
    println!("{}", some_string);
}// here, some_ String out of scope and call 'drop'. Backup memory has been released.


fn makes_ copy(some_ integer: i32) { // some_ Integer into scope
    println!("{}", some_integer);
}// here, some_ Integer is out of scope. Nothing special happened.

Return value and scope

The return value can also transfer ownership, for example:

fn main() {
    let s1 = gives_ ownership();         // gives_ Ownership moves its return value to S1

    Let S2 = string:: from ("hello"); // S2 enters the scope

    let s3 = takes_ and_ gives_ Back (S2); // S2 is moved into takes_ and_ gives_ Back, its return value is also moved to S3
                                       
}// here, S3 is out of scope and memory is released. S2 is out of scope but moved, so nothing happens. S1 is out of scope and memory is released.

fn gives_ ownership() -> String {             // gets_ Ownership moves its return value to the function that called it

    let some_ string = String::from("hello"); // some_ String into scope

    some_ string                              // some_ The string is returned and moved to the call gives_ In the function of ownership
}

// take_ and_ gives_ Back will get a string and return a
fn takes_ and_ gives_ back(a_ string: String) -> String { // a_ String into scope
    a_ string  // a_ The string is returned and moved to the call takes_ and_ gives_ In the function of back
}

Ownership of a variable follows the same pattern each time: assign a value to another variable and move it. When a variable containing data on the heap is out of scope, the value is deleted unless the data has been handed over to another variable.

Having ownership and then returning ownership of all the features is a bit tedious. What if we want functions to use values instead of ownership? It’s very annoying that in addition to any data that we might want to return from the body of the function, we need to pass it back if we want to use them again.

You can use tuples to return multiple values, for example:

fn main() {
    let s1 = String::from("hello");

    let (s2, len) = calculate_length(s1);

    println!("The length of '{}' is {}.", s2, len);
}

fn calculate_length(s: String) -> (String, usize) {
    Let length = s.len(); // len() returns the length of a string

    (s, length)
}

But it’s too much form and too much work for a concept that should be very common. Fortunately for us, rust has the function of this concept, which is called reference.