Considering a code like this:
std::string str = "abcdef";
const size_t num = 50;
const size_t baselen = str.length();
while (str.length() < num)
str.append(str, 0, baselen);
Is it safe to call std::basic_string<T>::append()
on itself like this? Cannot the source memory get invalidated by enlarging before the copy operation?
I could not find anything in the standard specific to that method. It says the above is equivalent to str.append(str.data(), baselen)
, which I think might not be entirely safe unless there is another detection of such cases inside append(const char*, size_t)
.
I checked a few implementations and they seemed safe one way or another, but my question is if this behavior is guaranteed. E.g. "Appending std::vector to itself, undefined behavior?" says it's not for std::vector
.
According to §21.4.6.2/§21.4.6.3:
The function [
basic_string& append(const charT* s, size_type n);
] replaces the string controlled by *this with a string of length size() + n whose first size() elements are a copy of the original string controlled by *this and whose remaining elements are a copy of the initial n elements of s.
Note: This applies to every append
call, as every append
can be implemented in terms of append(const charT*, size_type)
, as defined by the standard (§21.4.6.2/§21.4.6.3).
So basically, append
makes a copy of str
(let's call the copy strtemp
), appends n
characters of str2
to strtemp
, and then replaces str
with strtemp
.
For the case that str2
is str
, nothing changes, as the string is enlarged when the temporary copy is assigned, not before.
Even though it is not explicitly stated in the standard, it is guaranteed (if the implementation is exactly as stated in the standard) by the definition of std::basic_string<T>::append
.
Thus, this is not undefined behavior.
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