What are the differences between `String` and `str` in Rust?

In Rust, String and str (usually used as &str) are both used to handle UTF-8 encoded strings, but they serve distinct purposes. Here’s a detailed breakdown of their differences, along with examples:

1. Ownership and Mutability

AspectStringstr (&str)
OwnershipOwned type (heap-allocated).Borrowed slice (reference to UTF-8 data).
MutabilityMutable (can grow/shrink).Immutable (fixed view into data).
StorageHeap-allocated buffer.Points to data in heap, stack, or binary.

Example:

// String: Owned, mutable
let mut s = String::from("hello");
s.push_str(" world"); // Modify the String

// &str: Immutable reference
let s_literal: &str = "hello"; // Static string slice (stored in binary)
let slice: &str = &s[0..5]; // Borrowed slice from a String

2. Memory Representation

  • String:
  • Contains a pointer to the heap-allocated buffer, a length (current data size), and a capacity (allocated space).
  • Example: String::from("hello") allocates memory on the heap to store "hello".
  • str (&str):
  • A “fat pointer” containing a pointer to the data and its length.
  • Does not own the data; it’s a view into existing data (e.g., a String or a static string).

Example:

let s = String::from("hello");
let slice: &str = &s; // Points to the String's heap data
let static_slice: &str = "world"; // Points to static memory (binary)

3. Use Cases

Use CaseStringstr (&str)
Modify/own dataUse when you need to mutate or own the string.Use for read-only access or temporary views.
Function parametersPass String to transfer ownership.Pass &str to avoid unnecessary copies.
Storing textStore dynamic text (e.g., user input).Reference fixed text (e.g., literals).

Example (Function Parameters):

// Accepts &str for flexibility
fn print_text(text: &str) {
    println!("{}", text);
}

let s = String::from("hello");
print_text(&s); // Coerces String to &str
print_text("world"); // Directly pass a literal &str

4. Conversions

&str to String (Clone/Allocate):

let s_slice: &str = "hello";
let s_string: String = s_slice.to_string(); // or String::from(s_slice)

String to &str (Borrow):

let s = String::from("hello");
let s_slice: &str = &s; // Implicit deref coercion (String → &str)

5. Methods and Traits

  • String:
  • Methods to modify the string: push_str, pop, clear, etc.
  • Implements Deref<Target = str>, so all str methods work on String.
  • str (&str):
  • Read-only methods: len, contains, split, etc.
  • Cannot modify the underlying data.

Example:

let mut s = String::from("rust");
s.push_str("acean"); // Modify the String
assert_eq!(s, "rustacean");

let slice = &s[0..4];
assert_eq!(slice, "rust"); // Read-only slice

6. Lifetimes

  • String:
  • Owned data: no lifetime annotations needed.
  • Valid until it’s dropped (goes out of scope).
  • &str:
  • Borrowed data: requires explicit lifetime annotations if not static.
  • Must not outlive the data it references.

Example:

fn get_slice<'a>(s: &'a String) -> &'a str {
    &s[0..2] // Slice tied to the String's lifetime
}

let s = String::from("hello");
let slice = get_slice(&s); // Valid as long as `s` exists

7. Performance

  • String:
  • Overhead: Manages heap memory (pointer, length, capacity).
  • Flexible but slightly heavier for temporary data.
  • &str:
  • Lightweight: Only a pointer and length.
  • Ideal for read-only operations (no allocation needed).

Summary Table

FeatureStringstr (&str)
OwnershipOwnedBorrowed
MutabilityMutableImmutable
StorageHeapHeap, stack, or binary
LifetimeOwned (no annotations)Borrowed (requires annotations)
Use CaseDynamic text manipulationRead-only views or literals

When to Use Which

  • Use String when:
  • You need to modify or own the string.
  • Constructing dynamic strings (e.g., from user input).
  • Use &str when:
  • You need a read-only view of a string.
  • Passing string data to functions without transferring ownership.

By understanding these differences, you can write efficient and idiomatic Rust code.

Leave a Reply

Your email address will not be published. Required fields are marked *