Understanding Strings in Rust: `String` vs String Literals (`&str`)
Source: Dev.to
String literals (&str)
- Fixed, immutable sequences of UTF‑8 bytes known at compile time.
- Stored directly in the program’s binary (read‑only static memory).
- Zero‑cost to use: the compiler embeds the bytes, and at runtime only a fat pointer (pointer + length) is created on the stack or in a register.
- Lifetime is
'static– they live for the entire duration of the program.
let s: &str = "hello";
"hello"is placed in the read‑only data section of the executable.- No heap allocation, no system calls – just a pointer and a length.
String
- A growable, owned, mutable UTF‑8 buffer allocated on the heap.
- Can be modified (e.g.,
push_str,push). - Consists of three parts stored on the stack: a pointer to the heap buffer, its length, and its capacity.
let s = String::from("hello");
- Allocates memory on the heap, copies
"hello"into it, and manages the buffer’s lifetime automatically (freed when it goes out of scope).
Comparison
| Aspect | &str (string literal) | String |
|---|---|---|
| Mutability | Immutable | Mutable |
| Memory location | Read‑only binary section (static) | Heap (growable) |
| Creation | "hello" or &"hello" | String::from("hello") |
| Performance | Faster access, no allocation | Slower due to heap allocation |
| Typical use case | Static text, function parameters | Dynamic string building |
Storage details
| Type | Storage location | Details |
|---|---|---|
&str | Read‑only binary section | Pointer + length lives temporarily on the stack; the bytes are baked into the executable. |
String | Heap | Growable buffer; pointer, length, and capacity stored on the stack. |
Allocation and runtime cost
| Type | Heap allocation? | Relative speed |
|---|---|---|
&'static str | ❌ None | Very fast |
String | ✅ Yes | Slower (heap ops) |
String literals aren’t “faster at allocating”; they simply avoid runtime heap allocation altogether.
Example: Using a string literal
let s = "hello"; // `s` is a `&'static str`
- The bytes for
"hello"are already part of the binary. - At runtime Rust creates only a small reference (pointer + length) on the stack.
Example: Creating a String
let s = String::from("hello");
- Allocates heap memory, copies the bytes, and stores the metadata on the stack.
- The buffer is freed automatically when
sgoes out of scope.
Summary
&str– immutable, compile‑time known, stored in static read‑only memory, zero‑cost to reference.String– mutable, heap‑allocated, can grow or shrink, incurs allocation overhead.
Understanding these differences helps you choose the right type for a given situation: use &str for static text and function arguments, and String when you need a mutable, dynamically built string.