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 ofs2
, 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?
In many programming languages, string concatenation is a binary infix operator. The + (plus) operator is often overloaded to denote concatenation for string arguments: "Hello, " + "World" has the value "Hello, World".
In certain formalisations of concatenation theory, also called string theory, string concatenation is a primitive notion . In many programming languages, string concatenation is a binary infix operator. The + (plus) operator is often overloaded to denote concatenation for string arguments: "Hello, " + "World" has the value "Hello, World".
?: In formal language theory and computer programming, string concatenation is the operation of joining character strings end-to-end. For example, the concatenation of "snow" and "ball" is "snowball". In certain formalisations of concatenation theory, also called string theory, string concatenation is a primitive notion .
For two sets of strings S1 and S2, the concatenation S1S2 consists of all strings of the form vw where v is a string from S1 and w is a string from S2, or formally S1S2 = { vw : v ∈ S1, w ∈ S2 }.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With