c++ – Is it safe to append std::string to itself?

c++ – Is it safe to append std::string to itself?

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 (lets 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.

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 *this?

Nothing at all.

The only requirement of s is:

s points to an array of at least n elements of charT.

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.

c++ – Is it safe to append std::string to itself?

Leave a Reply

Your email address will not be published. Required fields are marked *