Difference Between String and str in Rust

Alex Garella

18th March 2023

In Rust, there are two main string types: String and str.

The primary differences between them are in ownership, mutability, and how they are stored in memory.

String

  • Growable, mutable, owned, heap-allocated string type.
  • Represented as a Vec<u8> under the hood, so it can be resized.

Usage

  • When you need a modifiable string, e.g., appending, inserting, or removing characters.
  • When the size of the string is unknown or may change during runtime.
  • When you want to pass ownership of the string to another function or return it from a function.

Downsides

  • Less efficient when dealing with constant or fixed-length strings due to heap allocation and resizing operations.
  • Potential performance overhead due to heap allocation and deallocation.

Code example

fn main() { let mut s = String::from("Hello"); // Create a new String with content "Hello" s.push_str(", world!"); // Append the string ", world!" to the original String println!("{}", s); // Output: "Hello, world!" }

str

  • Immutable, borrowed, fixed-length, stack- or heap-allocated string slice.
  • Often seen in its borrowed form, &str.

Usage

  • When you need a constant, fixed-length string or a read-only view of a String.
  • When you want to avoid heap allocation for better performance.
  • When you want to create a function that accepts both String and &str by using &str as the input type.

Downsides

  • Cannot be modified, so it's not suitable for cases where you need to change the string.
  • Can lead to lifetime-related issues when borrowing from other string types, requiring explicit lifetime annotations in some cases.

Code example

fn main() { let s: &str = "Hello"; // Create a new &str with content "Hello" // The following line would produce a compile-time error since &str is immutable: // s.push_str(", world!"); println!("{}", s); // Output: "Hello" }

Converting between String and &str

Here is a code example of how to convert between String and &str

fn main() { let s = String::from("Hello"); // Create a new String with content "Hello" let s_slice: &str = &s; // Create a &str slice that borrows from the String println!("String: {}", s); // Output: "Hello" println!("&str: {}", s_slice); // Output: "Hello" }

Summary

  • Use String when you need a mutable, growable string.
  • Use str (usually in its borrowed form, &str) when you need an immutable, fixed-length string.

Subscribe to receive the latest Rust jobs in your inbox

Receive a weekly overview of Rust jobs by subscribing to our mailing list

© 2024 RustJobs.dev, All rights reserved.