ProgramGuru

References and read-only borrowing

References and read-only borrowing

A function that measures a name need not take ownership of it. A reference gives temporary access to a value owned elsewhere. Creating that access is borrowing. An &str parameter accepts a borrowed view of text, making it useful for both String values and string literals.

What you’ll learn

  • Read a name without consuming its String owner.
  • Explain why a borrowed reference must remain valid.

References and read-only borrowing in action

  1. main owns String

    Main owns the String.

    main owns String
  2. name_bytes borrows &str

    The function borrows its text while calculating the byte count, then returns four.

    name_bytes borrows &str
  3. main keeps the owner

    Main can still print name because the call did not consume it.

    main keeps the owner
Main owns the String. The function borrows its text while calculating the byte count, then returns four. Main can still print name because the call did not consume it. The reference does not extend the lifetime of the owned text.

References and read-only borrowing explained

The ampersand creates a reference. &name can coerce from &String to &str for this call. The function reads the text and returns its byte length without becoming responsible for dropping the String. Multiple shared references can coexist, provided access respects Rust’s borrowing rules.

Work through the Rust program

Save the complete source as main.rs in the Rust environment. No standard input is needed.

Rust 2024 · complete program

fn name_bytes(name: &str) -> usize { name.len() }
fn main() {
  let name = String::from("Diya");
  let count = name_bytes(&name);
  println!("Bytes: {count}");
  println!("Still available: {name}");
}

Expected output

Bytes: 4
Still available: Diya

Follow the execution

Main owns the String. The function borrows its text while calculating the byte count, then returns four. Main can still print name because the call did not consume it. The reference does not extend the lifetime of the owned text.

Try the complete program in the Rust compiler. For tests, Cargo commands and local files, use the specified local environment.

Try a small variation

Your task: Why can main still print name after the call?

Rust 2024 · complete program

fn name_bytes(name: &str) -> usize { name.len() }
fn main() {
  let name = String::from("Diya");
  let count = name_bytes(&name);
  println!("Bytes: {count}");
  println!("Still available: {name}");
}

Worked answer

The parameter borrowed the text through &str instead of taking a String by value. Ownership remains in main.

Mistakes and limits to recognize

An ordinary shared reference does not permit mutation of its referent; interior-mutability types provide controlled exceptions. Len measures UTF-8 bytes for str, not user-visible letters. Do not return a reference to a local value that will be dropped.

Check your understanding

Why can main still print name after the call?
Choose one answer. You can try again.

Answer and explanation

The parameter borrowed the text through &str instead of taking a String by value.

The parameter borrowed the text through &str instead of taking a String by value. Ownership remains in main.

Take the idea into your next program

The parameter borrowed the text through &str instead of taking a String by value. Ownership remains in main. An ordinary shared reference does not permit mutation of its referent; interior-mutability types provide controlled exceptions.

Further reading: the official Rust Book on references and read-only borrowing.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Mutable references and exclusive access →