c++ – Is it safe to append std::string to itself?
According to §22.214.171.124/§126.96.36.199:
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 (§188.8.131.52/§184.108.40.206).
append makes a copy of
str (lets call the copy
n characters of
strtemp, and then replaces
For the case that
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
Thus, this is not undefined behavior.
This is complicated.
One thing that can be said for certain. If you use iterators:
std::string str = abcdef; str.append(str.begin(), str.end());
then you are guaranteed to be safe. Yes, really. Why? Because the specification states that the behavior of the iterator functions is equivalent to calling
append(basic_string(first, last)). That obviously creates a temporary copy of the string. So if you need to insert a string into itself, youre guaranteed to be able to do it with the iterator form.
Granted, implementations dont have to actually copy it. But they do need to respect the standard specified behavior. An implementation could choose to make a copy only if the iterator range is inside of itself, but the implementation would still have to check.
All of the other forms of
append are defined to be equivalent to calling
append(const charT *s, size_t len). That is, your call to append above is equivalent to you doing
append(str.data(), str.size()). So what does the standard say about what happens if
s is inside of
Nothing at all.
The only requirement of
spoints to an array of at least
Since it does not expressly forbid
s pointing into
*this, then it must be allowed. It would also be exceedingly strange if the iterator version allows self-assignment, but the pointer&size version did not.