let addr2: String = String::from("14 E 9th Street");
addr2.push_str(" South");
let addr2 = addr2 + " South";
Which of the two lines above is better? Does it make a difference?
Thanks,
Ken
let addr2: String = String::from("14 E 9th Street");
addr2.push_str(" South");
let addr2 = addr2 + " South";
Which of the two lines above is better? Does it make a difference?
Thanks,
Ken
Both works fine, so it's mainly a matter of taste. In theory, the one using +
will allocate a new String for the "sum" before dropping the old, while push_str will extend the existing allocation. But in practice, I think the compiler will probably optimize away the difference in most cases. Depending on which parts are hard-coded and which comes from a variable, I often use format!
, as in:
let addr2 = format!("{addr2} South"); // maybe?
let south = " South";
let addr2 = format!("14 E 9th Street{south}"); // or like this?
Using format!
may not really make sense in this example, but taking a step back and considering where the parts come from, I often find that it can make it all clearer.
Hi! The first one is better logically, but practically it doesn't really make sense in terms of memory usage. Anyway, there may be performance overhead, so imho the first one is the best choice.
No, both will work the same way, reusing addr2
's buffer if enough space is available.
There's no difference. +
calls push_str
under the hood.
Rust avoids the performance footgun many other languages have where +
allocates a new string. It can append directly to the input string because fn add(self, other: &str) -> String
consumes the left operand.
impl Add<&str> for String
Implements the
+
operator for concatenating two strings.This consumes the
String
on the left-hand side and re-uses its buffer (growing it if necessary). This is done to avoid allocating a newString
and copying the entire contents on every operation, which would lead to O(n^2) running time when building an n-byte string by repeated concatenation.The string on the right-hand side is only borrowed; its contents are copied into the returned
String
.
impl Add<&str> for String {
type Output = String;
#[inline]
fn add(mut self, other: &str) -> String {
self.push_str(other);
self
}
}
Aahh! Thank you. That's a relief. Excellent clarity in explaining.
Yes. I had also tried the latter. Worked fine. But I had no clue which is most efficient. I am leaning towards the push as it is obvious (as to what is intended) and (I am guessing) more effecient.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.