Some quesitons about &String and &mut String and String

fn main() {
    let mut s =  String::from("hello, ");
    let p = &mut s;
    println!("{}", s);

In this program, I define p as mut borrow of s. And then i use the method p.push_str("world"). So i have two questions.

  1. Var s is a struct String. Including pointer, used length, total length. On the same time, p is a struct &str. Including pointer, length. So why do s own the ownership of str and p don't have? Is there another sign which means ownership in complier?
  2. In the statement p.push_str("world"); , if there is a auto derefference so the actual code is *(p.pointer).push_str("")?
  3. rust lang designer's design about &String, i think the type &String and &mut String have the same struct, but exist a sign about if the struct can use pointer to change the str's value. Is my understanding right?

Hey, it's not once that you're informed to use codeblocks ``` to show code from here and here .

And to make your questions accessible, use correct English as much as possible.



No. p is of type &mut String, so it is a pointer to the location where s is stored. &String to &str only happens when requested or required.

Because that is how String is implemented. References (&T or &mut T for any type T) never own the thing they point to.

No. The method you are calling is String::push_str, and its signature is:

fn push_str(&mut self, string: &str)

The &mut self is a short way of writing self: &mut String. So, the first argument is a &mut String, which is what p is, so it can be passed directly without needing any dereferencing.

That line can also be written out as:

String::push_str(p, "world");


&String and &mut String are the same in memory: a single pointer to where a String is stored. The mut keyword indicates that the String value can be modified via the &mut String.

However, you are not necessarily modifying a str. For example, push_str modifies the String value itself, and might modify the underlying string data, or it might make a copy and modify that.

Edit: To clarify, having a &mut T allows you to modify the T, as well as anything that T contains. If T contains a &mut U, then you can also modify that U. You can continue chaining &mut _ references as deep as you like.


Ok, I will change it at once.


Sorry sir, I will use google translate next time. I got high marks in my English test, but it seems that I am too confident in my English skills. :pensive: :pensive: :pensive:

To take ownership you write this:

let a = String::from("hello");
let b = a;  // b is now the owner

I didn't mean to blame you. I just want to encourage you to express your thoughts better in English.


I've modified your OP (original post) by attaching your former code in screenshot and deleting your new code snippet to let the existing answer make sense. If you want to ask more questions based on your new code, feel free to append it as new replies.


Your answer enlightened me. I still have a few things I want to confirm with you.
1.&String and &str are different types. &String is just a pointer to a String struct. Only when it is used, it create a temporary &str struct, right?
2. Your answer says that references don't have ownership. But isn't String itself a struct who containing pointers? Why can it have ownership of str?
3. push_str() does not necessarily modify the original heap str'svalue. For example, if I want to add a long string but there is insufficient space, then a new space will be opened on the heap, the original str will be copied, and my new str will be inserted. ,Is it right?

Only when it's used wherever the &str is expected. It won't be converted unnecessarily, there must be some type explicitly annotated as &str (let binding, function argument, structure field, etc.) or an explicit operation like as_str().

It contains pointer (that is, it uses some memory besides the one directly reserved for it), but no references. And, more importantly, it not only contains pointer - it manages this pointer (by allocating and deallocating corresponding memory), and that's what is represented by ownership.


I see what you mean, I will learn how to use the tools provided by the platform.

1 Like

I understand, thank you.

Ownership is not completely defined by the language. It is a convention that library code collaborates with the language to create.

The way in which String owns the str is:

  1. When a (nonempty) String is created, its constructor allocates memory for the str.
  2. When that String is dropped, the same memory is deallocated.

Those two paired actions, which are done inside the code of String's functions, are what make String an owning pointer type rather than a non-owning one.

It is also possible to own values directly, by defining a struct with fields; the struct owns the values in the fields In this case, the language handles ensuring that the fields are always dropped and deallocated at the right times; no special code need be written.

This is what I mean when I say that ownership is a collaboration between the language and the libraries; it is a concern of both. The language keeps track of when to call Drop::drop(), and the libraries implement it to do the right things (in the cases where the right thing is not just the default behavior).


In other words, a variable with ownership of a value will use drop() to release the memory space used for storing the value at the end of its lifetime, while borrowing only uses and stops using it, and does not release its memory space.

Every variable's value is dropped (except when the value is moved out of the variable).

It's just that dropping a reference does nothing.

This is not quite accurate, because references do have a certain special lenience. But that's a refinement of the fundamental model; the fundamental model is that every value is automatically dropped (except in special cases), but the drop doesn't necessarily have any effects.

1 Like

I understand your explanation, thank you!