In this lesson, you will learn how Rust distinguishes between fixed-size string literals and dynamic, heap-allocated strings to ensure memory safety.
The Two Faces of Strings
In Rust, not all strings are created equal. When you write let greeting = "Hello";, you are creating a string literal, which is a &str (a string slice). Because this text is hardcoded into your program's binary, it has a "static" lifetime. It is a fixed-size sequence of bytes that exists for the entire duration of your program.
However, often you need strings that can grow, shrink, or be modified at runtime. For these, we use the String type.
Ownership and the Heap
A String is a more sophisticated animal. Unlike a &str, a String is stored on the heap. When you create a String (e.g., String::from("Hello")), Rust allocates enough space on the heap to hold those characters.
The String owns its data. If you pass a String to a function, you are transferring that ownership. If you only want a function to read the data, you pass a reference (&str), just as you learned with other types.
Consider this distinction:
fn main() {
// A fixed-size slice pointing to binary memory
let static_str: &str = "Fixed";
// A heap-allocated, owned buffer
let mut dynamic_str: String = String::from("Dynamic");
dynamic_str.push_str(" content"); // We can expand this!
}
Why does this matter for Ownership?
Because the String owns its memory on the heap, Rust follows the RAII (Resource Acquisition Is Initialization) pattern you’ve studied: when a String variable goes out of scope, Rust automatically triggers the deallocation of that heap memory.
If you try to point to a String that has gone out of scope, the borrow checker will stop you, preventing the common "use-after-free" bugs found in other languages. You are effectively managing a buffer that can change shape, but the rules of ownership ensure that the memory is cleaned up exactly once, and only when it is safe to do so.
Key Takeaway: Use &str for fixed, read-only sequences, and use String when you need an owned, growable buffer that lives on the heap.