Let's take a look at some code that includes a function that takes in a string and returns the length, then, after that function, prints out both the contents of the string and the length:
main.rs
fnmain(){let s1 =String::from("hello");let(s1, len)=calculate_length(s1);println!("The length of '{}' is {}.", s1, len);}fncalculate_length(s:String)->(String,usize){// s is a String(s.clone(), s.len())}// Here, s goes out of scope and `drop` is called
That is... sorta gnarly. We could potentially copy s1 into calculate_length instead of returning a tuple, but either way... not great! Luckily, Rust does not actually require us to do this. With Rust, you can pass a value as a reference, which enables the function or variable to get the contents without taking ownership. You do this by putting an ampersand (&) in front of both the type and the variable when it's passed, like so:
main.rs
fnmain(){let s1 =String::from("hello");let len =calculate_length(&s1);println!("The length of '{}' is {}.", s1, len);}fncalculate_length(s:&String)->usize{// s is a reference to a String s.len()}// Here, s goes out of scope. But because it does not have ownership// of what it refers to, nothing happens.
The two big changes here are calculate_length(&s1) and calculate_length(s: &String). By default, if something is a reference, it is immutable. You can make a reference mutable by using &mut instead of &. Here's an example:
Knowing this, let's go ahead and redo our code for the team scores (used previously here and here):
In summary, here are the rules for references:
At any given time, you can have either but not both of: