References Basics
In this page:
let r = &value;
fn name(param: &Type) {
// borrows without owning
}
name(&value);
Creating a Reference
Prefixing a variable with & creates a reference to its value instead of moving or copying it. The function receiving the reference can read the data without owning it.
Example: Creating a Reference
// Define the function `print_value` taking `v`
fn print_value(v: &i32) {
// Print "Value is {}" to the console, substituting in `v` (with a trailing newline)
println!("Value is {}", v);
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `number`, set to `42`
let number = 42;
print_value(&number);
// Print "Still usable: {}" to the console, substituting in `number` (with a trailing newline)
println!("Still usable: {}", number);
}
Login to try C/C++/Java/PHP code in the editor
References to Strings
References are especially useful for larger data like String, letting a function read the content without taking ownership away from the caller.
Example: References to Strings
// Define the function `print_length` taking `s`
fn print_length(s: &String) {
// Print "Length: {}" to the console, substituting in `s.len()` (with a trailing newline)
println!("Length: {}", s.len());
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `name`, set to `String::from("Ferris")`
let name = String::from("Ferris");
print_length(&name);
// Print "name is still valid: {}" to the console, substituting in `name` (with a trailing newline)
println!("name is still valid: {}", name);
}
Login to try C/C++/Java/PHP code in the editor
References Are Immutable by Default
A plain reference &value only allows reading, not writing, the data it points to. This matches the default immutability of let bindings.
Example: References Are Immutable by Default
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `data`, set to `vec![1, 2, 3]`
let data = vec![1, 2, 3];
// Declare an immutable variable `reference`, set to `&data`
let reference = &data;
// Print "Through reference: {:?}" to the console, substituting in `reference` (with a trailing newline)
println!("Through reference: {:?}", reference);
}
Login to try C/C++/Java/PHP code in the editor
The Original Owner Remains Valid
Because borrowing with & does not transfer ownership, the original variable remains fully usable both during and after the borrow, unlike a move.
Example: The Original Owner Remains Valid
// Define the function `describe` taking `s`
fn describe(s: &String) {
// Print "Describing: {}" to the console, substituting in `s` (with a trailing newline)
println!("Describing: {}", s);
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `word`, set to `String::from("borrow")`
let word = String::from("borrow");
describe(&word);
describe(&word);
// Print "word used three times total: {}" to the console, substituting in `word` (with a trailing newline)
println!("word used three times total: {}", word);
}
Login to try C/C++/Java/PHP code in the editor
- Forgetting the
&when calling a function that expects a reference, causing a type mismatch error. - Assuming a reference is a copy of the data -- it is only a pointer to the original value, not a new value.
- Trying to modify data through an immutable reference, which the compiler rejects.
- A reference, written
&value, lets you access a value without taking ownership of it. - References are immutable by default, just like
letbindings. - Referencing a value instead of passing it by value is called borrowing.
- The referenced value's owner is unaffected and can still be used after the borrow ends.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: