String
Strings in Rust are a fundamental aspect of the language, and mastering them is key to effective programming. Unlike many other system programming languages, Rust enforces strict memory safety guarantees, and this shapes how strings are handled—both on the stack and the heap.
str vs String in Rust
In Rust, there are two primary string types:
str: String Slice
- A
strrepresents a borrowed reference to a string, typically a sequence of UTF-8 encoded bytes. - It is a view into some data, rather than owning the data.
stris immutable—you cannot change it directly.stris typically stored on the stack but references data stored elsewhere, often in the program’s binary (for string literals) or the heap.- It's always a reference, so you’ll see it in code as
&str, signifying it’s a borrowed reference to a string.
Example:
let hello: &str = "Hello, world!";
In this case, "Hello, world!" is stored in the binary, and hello is a reference to this string slice.
String: Growable, Heap-Allocated String
- A
Stringis an owned string stored on the heap. - Since it's heap-allocated, it can grow in size dynamically.
- You can modify a
Stringby appending or removing characters. - Because it owns its data, a
Stringcan be passed around, transferred between functions, or manipulated in ways astrcannot.
Example:
let mut hello = String::from("Hello");
hello.push_str(", world!");
In this case, hello starts as a String containing "Hello", but it can be modified to append ", world!".
Differences Between str and String
| Aspect | str | String |
|---|---|---|
| Ownership | Borrowed (does not own the data) | Owns the data |
| Mutability | Immutable | Mutable (can grow or shrink) |
| Storage Location | Stack (but references data elsewhere, often heap or binary) | Heap (allocates memory dynamically) |
| Common Use Cases | String literals, borrowed data | When ownership or dynamic behavior is needed |
Why is This Different From Other Languages?
Rust’s handling of strings is unique due to its ownership model and memory safety guarantees. In languages like C or C++, strings are often managed manually, leading to potential memory leaks or segmentation faults. In contrast:
- Rust guarantees that all memory is properly cleaned up when it’s no longer needed, using its ownership and borrowing system.
- Strings in Rust avoid the problems of dangling pointers and double frees common in manual memory management.
For example, in C you might dynamically allocate memory for a string and need to explicitly free it. In Rust, the
compiler ensures that when a String goes out of scope, its memory is automatically deallocated.
Key Points on Memory Efficiency
- Heap Allocations: While
Stringprovides flexibility with dynamic growth, heap allocations are more expensive than stack allocations due to the overhead of managing dynamic memory. For small, fixed-size strings, consider using&strto avoid heap allocation. - Copying and Cloning: Cloning a
Stringmeans copying the entire heap-allocated buffer, which can be expensive for large strings. Cloning a&str(or borrowing it) is just copying the reference, which is cheap.