codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

© 2026 codingstuff.io. All rights reserved.

Built with ❤️ for developers everywhere

/
/
All Tutorials
🦀

Rust

15 / 58 topics
13Ownership14Borrowing15References16Slices
Tutorials/Rust/References
🦀Rust

References

Updated 2026-05-15
10 min read

References

Introduction

In Rust, the concept of ownership is a core principle that ensures memory safety without a garbage collector. Ownership rules dictate how data is managed and transferred between variables. However, sometimes you might want to avoid transferring ownership when passing data around. This is where references come into play.

References allow you to refer to a value without taking ownership of it. They are immutable by default, meaning the data they point to cannot be modified through the reference. If you need mutable access, you can use mutable references, but there are strict rules around them to prevent data races and ensure safety.

Concept

A reference in Rust is created using the & symbol. When you create a reference, you are essentially borrowing the value without taking ownership. The original variable retains its ownership, and the reference allows other parts of your code to access the value temporarily.

Rules for References

  1. Multiple immutable references or one mutable reference: You can have any number of immutable references to a single piece of data at any given time, or exactly one mutable reference. But not both.
  2. References must always be valid: A reference in Rust is guaranteed to point to a valid memory location for as long as the reference exists.

These rules ensure that while you can share access to data, you cannot accidentally introduce bugs related to concurrent modifications or invalid memory accesses.

Examples

Let's explore some examples to understand how references work in Rust.

Immutable References

Here’s an example of using immutable references:

Rust
1fn main() {
2 let s1 = String::from("hello");
3
4 let len = calculate_length(&s1);
5
6 println!("The length of '{}' is {}.", s1, len);
7}
8
9fn calculate_length(s: &String) -> usize {
10 s.len()
11}

In this example:

  • &s1 creates an immutable reference to the string s1.
  • The function calculate_length takes a reference to a String as its parameter.
  • Inside calculate_length, we call s.len() on the borrowed value, which does not take ownership of s.

The original s1 remains valid and can be used after calling calculate_length.

Mutable References

Mutable references allow you to modify the data they point to. Here’s how you can use mutable references:

Rust
1fn main() {
2 let mut s = String::from("hello");
3
4 change(&mut s);
5
6 println!("The modified string is '{}'.", s);
7}
8
9fn change(some_string: &mut String) {
10 some_string.push_str(", world");
11}

In this example:

  • &mut s creates a mutable reference to the string s.
  • The function change takes a mutable reference to a String as its parameter.
  • Inside change, we modify the borrowed value by calling push_str.

It's important to note that you can only have one mutable reference to a particular piece of data in a particular scope. This restriction prevents data races.

Combining Immutable and Mutable References

You cannot mix immutable and mutable references within the same scope:

Rust
1fn main() {
2 let mut s = String::from("hello");
3
4 let r1 = &s; // no problem
5 let r2 = &s; // no problem
6 let r3 = &mut s; // BIG PROBLEM
7
8 println!("{} and {}", r1, r2);
9}

In this example, the code will not compile because you cannot have both immutable references (r1 and r2) and a mutable reference (r3) to the same data in the same scope.

Dangling References

Rust also prevents dangling references—references that point to invalid memory. The borrow checker ensures that all references are valid for as long as they are used:

Rust
1fn main() {
2 let reference_to_nothing = dangle();
3}
4
5fn dangle() -> &String {
6 let s = String::from("hello");
7
8 &s
9}

In this example, the code will not compile because dangle tries to return a reference to a local variable s, which is dropped at the end of the function. The borrow checker prevents this by ensuring that all references are valid.

What's Next?

Now that you understand how references work and how they help manage ownership without transferring it, the next step is to explore slices. Slices allow you to reference a contiguous sequence of elements in a collection, such as a string or an array, without taking ownership. This will give you more flexibility when working with data in Rust.

Stay tuned for the next section on slices!


PreviousBorrowingNext Slices

Recommended Gear

BorrowingSlices