What are the differences between Rust's `String` and `str`?

前端 未结 9 819
醉梦人生
醉梦人生 2020-11-22 05:11

Why does Rust have String and str? What are the differences between String and str? When does one use String

9条回答
  •  终归单人心
    2020-11-22 05:42

    String is the dynamic heap string type, like Vec: use it when you need to own or modify your string data.

    str is an immutable1 sequence of UTF-8 bytes of dynamic length somewhere in memory. Since the size is unknown, one can only handle it behind a pointer. This means that str most commonly2 appears as &str: a reference to some UTF-8 data, normally called a "string slice" or just a "slice". A slice is just a view onto some data, and that data can be anywhere, e.g.

    • In static storage: a string literal "foo" is a &'static str. The data is hardcoded into the executable and loaded into memory when the program runs.

    • Inside a heap allocated String: String dereferences to a &str view of the String's data.

    • On the stack: e.g. the following creates a stack-allocated byte array, and then gets a view of that data as a &str:

        use std::str;
      
        let x: &[u8] = &[b'a', b'b', b'c'];
        let stack_str: &str = str::from_utf8(x).unwrap();
      

    In summary, use String if you need owned string data (like passing strings to other threads, or building them at runtime), and use &str if you only need a view of a string.

    This is identical to the relationship between a vector Vec and a slice &[T], and is similar to the relationship between by-value T and by-reference &T for general types.


    1 A str is fixed-length; you cannot write bytes beyond the end, or leave trailing invalid bytes. Since UTF-8 is a variable-width encoding, this effectively forces all strs to be immutable in many cases. In general, mutation requires writing more or fewer bytes than there were before (e.g. replacing an a (1 byte) with an ä (2+ bytes) would require making more room in the str). There are specific methods that can modify a &mut str in place, mostly those that handle only ASCII characters, like make_ascii_uppercase.

    2 Dynamically sized types allow things like Rc for a sequence of reference counted UTF-8 bytes since Rust 1.2. Rust 1.21 allows easily creating these types.

提交回复
热议问题