[Avg. reading time: 4 minutes]

Borrowing

Borrowing allows you to access data without taking ownership.

Instead of moving a value, you pass a reference using &.

This prevents ownership transfer and keeps the original value usable.


Problem: Ownership Transfer

// This will fail

fn printname(p_name: String) {
    println!("{p_name}");
}

fn main() {
    let name = String::from("Rachel");
    printname(name);
    printname(name); // error: value moved
}

Why this fails?

  • String does not implement Copy
  • Ownership moves into printname
  • name becomes invalid after first call

How to fix it?

Borrowing Concept

// Instead of passing the actual value, passing the Reference / Borrow operator

fn printname(p_name:&String){
    println!("{p_name}-Stack {:p}-> Heap {:p}",&p_name,p_name.as_ptr())
}

// by default len() returns usize.

fn get_length(p_name: &String) -> i8 {
    let name_length:i8 = p_name.len() as i8;
    name_length
}

fn main() {
    let name:String = String::from("Rachel");
    printname(&name);
    printname(&name);
    let name_length = get_length(&name);
    println!("Length is {name_length}");
}

What changed:

  • &String means “borrow”
  • Ownership stays in main
  • Multiple immutable borrows are allowed
  • No data is copied
  • No heap reallocation happens

Using String.clone()

// String.clone()

fn printname(name:String){
    println!("{},{:p},{:p}",name,&name,name.as_ptr())
}

fn main() {
    let name:String = String::from("Rachel");
    printname(name.clone());
    printname(name.clone());
    printname(name);
}

What clone() does:

  • Allocates new heap memory
  • Copies the bytes
  • Creates a completely independent value

Important:

  • clone() is explicit and potentially expensive
  • Borrowing is usually preferred
  • Clone only when you need separate ownership

#borrow #cloneVer 2.0.10

Last change: 2026-02-11