0

To my understanding the String type is allocated on the heap in rust and the pointer and length of it on the stack. The &str type is allocated on the stack directly due to its fixed size.

Now if I us as_str() on a String type in becomes a &str type. Does that mean the the content of the String type which is on the heap gets copied to the stack? Or is it a reference to that content that is on the heap?

FreddyC
  • 11
  • 1
  • 3
  • 1
    `&str` like `String` is a pointer to some memory, unlike `String` it does not carry `capacity` information and it does not own the allocation, it does *not* store the string data itself. – cafce25 Aug 10 '23 at 08:50
  • 1
    [Chapter 4](https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html) has some good pictures on it specifically [4.3 The slice type](https://doc.rust-lang.org/book/ch04-03-slices.html) is relevant since `str` is a string *slice* – cafce25 Aug 10 '23 at 08:57
  • 1
    Does this answer your question? [What are the differences between Rust's \`String\` and \`str\`?](https://stackoverflow.com/questions/24158114/what-are-the-differences-between-rusts-string-and-str) – cafce25 Aug 10 '23 at 08:58

1 Answers1

0

The &str type is allocated on the stack directly due to its fixed size.

Like with String, the pointer and length -- the actual things that make up the type -- are stored on the stack, but in the case of &str, the pointed-to string data may live anywhere: if it came from a String, the data lives where the String owns it on the heap, while if it came from an array, it lives on the stack.

Roughly speaking, a &str is represented by

struct StrRef {
    data: *const u8,
    len: usize,
}

So this is constructed from a String by doing something like

let owned = String::from("hello");
let borrowed = StrRef {
    data: owned.as_ptr(), // via Deref<Target = str>,
    len: owned.len(),
};

More strictly speaking, str (without the &) is a dynamically sized type, which means that a reference to it (&str) is wide -- it stores both a pointer to the data and some metadata, which in the case of str and [T] is a usize representing the length.

This wide pointer ends up looking something like StrRef above, but the exact representation of wide pointers is (currently) not a stable part of the language; str and [T] are treated specially by the compiler, as is dyn Trait (where the metadata is a pointer to a vtable).

Mac O'Brien
  • 2,407
  • 18
  • 22