Clarifications about lifetime

  • Why there is lifetime for strings, and no lifetime for numbers.
  • Why there is lifetime for str and no lifetime for String
  • What is the different between string slices &str and string literal String
  • What is &'static str and the difference between it and &'a str
  1. There is a lifetime 'static for strings because you don't want to copy around the entire string, and it's embedded into your application so it's a reference to the embedded string
  2. Because String is basically a manager for a str, and str refers to the data that is !Sized so you can't easily pass it around
  3. String slices (str) are the very data that is encoded as UTF-8, while String is more of a manger around a str that allows resizing, reallocating etc.
  4. &'static str is a string that will live forever, i.e., a string that is hard-coded into your application, such as "abc" which will live forever as a hard-coded bit of information, while &'a str is a str with a lifetime attached that doesn't have to be 'static, meaning that it could be let my_str = my_string[..] or let my_str = "abc"
2 Likes

Adding on to @OptimisticPeach, str is unsized, so it must live behind a pointer, the cheapest safe pointer in Rust is a reference. References need lifetimes to enure their safety. String literals, &'static str, live in your application binary, along with all static variables. They have static lifetime because they live for as long as you need them to. String is a heap allocated growable string buffer. The difference between &'static str and &'a str is that the former lives for as long as you need it to, whereas the latter only as long as 'a, which is probably for less time than 'static.

3 Likes
  1. There is for references to numbers, like &i32. But numbers can be cheaply copied (they're a Copy type), so there's rarely a need to use references to them. Numbers have fixed size (e.g. i32 is 4 bytes), but str isn't (str of *"hello" is 5 bytes, str or *"bye" is 3 bytes), so it's not stored anywhere directly, because storage requirements can't be known.

  2. String is an owned type (owns it data), not a reference. References are only for data borrowed from somewhere else.

  3. String owns its data, and will free it when its gone. Slices never own their data, and will never free it by themselves. Plus, String can be extended. Slices can only be shortened.

  4. 'static is a special lifetime that means something won't be freed until your program exits. So 'static str lives "forever", and &'a str lives for as long as the thing where the 'a came from.

3 Likes

Thanks a lot.
If I understood correctly, then I've to use &str instead of String, as by this I'm saving memory instead of duplicating my item, and I should write something like:

pub fn hello(s: &str) -> String {
    format!("Hello, {}", s)
}

And call it as:

hello("rust");

Instead of writing:

pub fn hello(s: String) -> String {
    format!("Hello, {}", s)
}

and call it as:

hello(String::from("rust"));

Yes. It's also more flexible, because String can be cheaply borrowed as &str, so it works in cases where you have either &str or String.

1 Like