Who is the owner of a concatenated string once its owner goes out of scope?

Viewed 227

I am learning Rust and chapter 8.2 of the Rust Programming Language book raised some doubts:

let mut s1 = String::from("foo");
let s2 = "bar";
s1.push_str(s2);
println!("s2 is {}", s2);

If the push_str method took ownership of s2, we wouldn’t be able to print its value on the last line.

I understand this and the fact that the concatenation adds only the reference to the string and does not get its ownership. This should mean that if s2 goes out of scope or is changed, the concatenated string should be deallocated or changed but it is not happening:

let mut s1 = String::from("foo");
{
    let mut s2 = String::from("bar");
    s1.push_str(&s2[..]);
    println!("s2 is {}", s2);

    println!("s1 is {}", s1);
    s2 = String::from("lol");

    println!("s2 is {}", s2);
}
println!("Value after change is {}", s1);

Since the concatenated string is only a reference to the string s2 and s1 does not get the ownership of the string, once s2 goes out of scope, who is the owner of the concatenated string?

1 Answers

String and str are stored as contiguous arrays of UTF-8 bytes.

String "foo"                         &str "bar"
[ len: 3 | data:┐ ]                  [ len: 3 | data:┐ ]
                │                                    │
                v                                    v
                [ f | o | o ]   [ more memory... ]   [ b | a | r ]

When you do s1.push_str(&s2[..]), the bytes of s2 are copied to the end of the memory owned by s1 (possibly reallocating to make more room), leaving s2 as it is.

              ┌────────────────────┐
              v                    │
[ f | o | o | b | a | r ]        [ b | a | r ]

The fact that the underlying bytes must be contiguous means there's no way to perform a non-copying append operation with Rust's String/&str types. Such an operation would require a string type implemented as, for instance, a linked list of string chunks rather than a single contiguous array.

Related