What Are the Differences Between str and String in Rust?

In Rust, <span>str</span> and <span>String</span> are two core types for handling text data, and they have essential differences in memory management, ownership, and mutability. The table below summarizes their core differences for quick understanding:

Feature <span>String</span> <span>str</span> (<span>&str</span>)
Ownership Owns the data No ownership, it is a borrowed reference
Mutability Mutable Immutable
Storage Location Data is stored on the heap Data can exist in static memory (like literals) or as a view of heap data (like a part of a <span>String</span> reference)
Memory Management Allocated dynamically on the heap, can grow automatically Does not involve memory allocation, is a dynamically sized type (DST), typically used through a reference <span>&str</span>
Performance Characteristics Operations may involve memory allocation and copying, relatively high overhead Very efficient, only passing pointers and lengths, no extra overhead
Typical Use Cases Scenarios where string data needs to be dynamically constructed, modified, or owned Function parameters, string literals, slicing operations, or read-only access to existing strings

Detailed Explanation of String

<span>String</span> is a mutable string type provided by the standard library, with data stored on the heap, ownership, and a dynamically changing length.

  1. Creating a <span>String</span>:

  • Creating from a literal:
    let s = String::from("Hello");
    let s = "Hello".to_string();
  • Creating an empty string and appending content:
  • let mut s = String::new();
    s.push_str("Hello");
  • Modification and Operations: <span>String</span> supports various modification operations, such as:

    let mut s = String::from("Hello");
    s.push_str(" World!"); // Append string slice
    s.push('!'); // Append character
    s.replace("World", "Rust"); // Replace part of the content

    These operations may trigger reallocation of the underlying buffer to accommodate more data.

  • Detailed Explanation of str (&str)

    <span>str</span> is Rust’s string slice type, which is itself a dynamically sized type (DST) and is typically used as an immutable reference <span>&str</span>. It represents a read-only view of a valid UTF-8 encoded text.

    1. Creating an <span>&str</span>:

    • The type of string literals is usually <span>&'static str</span>:<span>let s: &str = "Hello";</span>
    • Borrowing from a <span>String</span>:
      let string = String::from("Hello"); let slice: &str = &string
    • Getting a partial slice (substring):
      let s = "Hello"; let sub: &str = &s[0..2]; // "He" (note that slice boundaries must be on character boundaries)
  • Common Operations: <span>&str</span> supports slicing, searching, and other read-only operations, but cannot directly modify its content.

    let greeting = "Hello, Rust!";
    println!("Length in bytes: {}", greeting.len());
    if let Some(idx) = greeting.find('R') { println!("'R' found at index: {}", idx); }
  • Mutual Conversion

    <span>String</span> and <span>&str</span> can be easily converted to each other:

    • <span>&str</span> to <span>String</span>: Use <span>to_string()</span> or <span>String::from()</span>. This allocates new memory on the heap and copies the data.

      let slice: &str = "hello";
      let owned_string: String = slice.to_string(); // or String::from(slice)
    • <span>String</span> to <span>&str</span>: Use <span>&</span> or <span>as_str()</span> method. This incurs no overhead, just creates a view pointing to the original <span>String</span> data. <span>let s = String::from("hello"); let slice: &str = &s // or s.as_str()</span>

    Usage Scenarios

    • Prefer using <span>&str</span> as function parameters: This allows the function to accept both references to <span>String</span> (<span>&String</span> will be automatically coerced to <span>&str</span>) and string literals (<span>&'static str</span>), providing greater flexibility.

      fn print_greeting(greeting: &str) { // Recommended to use &str
          println!("{}", greeting);
      }
    • Use <span>String</span> when ownership or modification is needed: For example, when reading content from files or networks, or when dynamic string concatenation is required.

    • Be aware of UTF-8 encoding: Rust strings are UTF-8 encoded.<span>len()</span> returns the number of bytes rather than the number of characters. To get the number of characters, use <span>s.chars().count()</span>. Directly accessing characters by index (like <span>s[0]</span>) is not allowed, as characters may consist of multiple bytes. When slicing strings, ensure that the indices fall on character boundaries, or it will cause a panic.

    Leave a Comment