Skip to content

/compare/rust/string-vs-str

Rust String vs &str: what is the difference?

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · rustc 1.98.1 (48a229cea 2026-09-01)updated
tool
Rust
compares
String vs &str

String owns its text: a heap buffer that can grow and is freed when the String is dropped. &str (a string slice) borrows text owned by someone else: a String, a string literal in the binary, or part of either. Store String in structs and return it from functions that build text; take &str as a parameter, because both &String and literals coerce to it.

Side by side

String&str
OwnershipOwns the data, frees it on dropBorrows data owned elsewhere
MutabilityGrowable with push_str, push, insertRead-only view
Layout (64-bit)Pointer + capacity + length (24 bytes)Pointer + length (16 bytes, a "fat pointer")
LiteralsString::from("hi"), "hi".to_string()"hi" has type &'static str
Function parameterTakes ownership (caller gives the value up or clones)Accepts &String, literals and slices
Conversion&s or s.as_str() gives &strto_string(), to_owned() or String::from() gives String

In code

bash
cat > main.rs <<'EOF'
fn shout(text: &str) -> String {
    text.to_uppercase()                  // builds and returns an owned String
}

fn main() {
    let mut owned: String = String::from("hello");
    owned.push_str(", world");           // String can grow
    let literal: &str = "rust";          // &'static str, lives in the binary
    let slice: &str = &owned[0..5];      // borrowed view into the String

    println!("{}", shout(&owned));       // &String coerces to &str
    println!("{}", shout(literal));
    println!("{}", shout(slice));
    println!("size_of String = {}", std::mem::size_of::<String>());
    println!("size_of &str   = {}", std::mem::size_of::<&str>());
}
EOF
rustc main.rs && ./main

Output

HELLO, WORLD
RUST
HELLO
size_of String = 24
size_of &str   = 16

Which one to use

  • Parameters: &str. A function fn f(s: &str) accepts &String, literals and slices; fn f(s: String) forces callers to give up or clone their string.
  • Struct fields: String, unless the struct is meant to borrow (then it needs a lifetime, struct Token<'a> { text: &'a str }).
  • Return values: String when the function creates new text; &str only when returning part of an input.

Sources