String vs &str in Rust

Both contain utf-8 encoded text, but:

  • String owns the data stored within it. When the String is deallocated the text data it stores is deallocated as well.
  • &str borrows data that is stored elsewhere (usually in a String), it doesn't store any text data of its own. When a &str is deallocated the data it points to is left untouched.

Handily, a &str can be shorter than the String it references. This helps make string handling fast and memory efficient as we can simply break up a pre-existing String into chunks that all just reference the original String, no heap allocations or data copying needed.

In the example below, text data is only allocated once when we read the file into memory. The rest of the strings are all just references to the original.

use std::fs::read_to_string;

fn main() {
// Reads text from a file and stores it in memory in a String
let input: String = read_to_string("src/example.txt").unwrap();

// Remove leading and trailing whitespace. No memory is copied on this line,
// `trimmed` just points to the parts of `input` that don't include leading
// or trailing whitespace.
let trimmed: &str = input.trim();

// No text data gets copied here either.
// Each `&str` representing a line of text simply points to data already
// stored in `input` above.
for line in trimmed.lines() {
println!("{}", line);
}
}

String literals

String literals in Rust are &strs.

When Rust compiles your code the text gets stored in the (read-only) data segment of the generated program, and the &str references that data. Because string literals live for the entire duration of the program they have a static lifetime, so the full type can be written as &'static str.

let string: &'static str = "Hello world";

Check out the Rust docs for more details on lifetimes and &str.