https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110945

--- Comment #11 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jonathan Wakely from comment #6)
> And _M_replace_dispatch creates a new copy anyway:
> 
>       _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
>                         _InputIterator __k1, _InputIterator __k2,
>                         std::__false_type)
>       {
>       // _GLIBCXX_RESOLVE_LIB_DEFECTS
>       // 2788. unintentionally require a default constructible allocator
>       const basic_string __s(__k1, __k2, this->get_allocator());
>       const size_type __n1 = __i2 - __i1;
>       return _M_replace(__i1 - begin(), __n1, __s._M_data(),
>                         __s.size());
>       }

When distance(k1, k2) > this->capacity() this function will make two copies of
[k1,k2) and allocate twice. So even with the checks for disjunct strings, we do
a lot more work than the copy construction benchmarks.

With this change we make a single allocation+copy and then do a cheap move
assignment:

--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1711,4 +1711,4 @@
         basic_string&
         assign(_InputIterator __first, _InputIterator __last)
-        { return this->replace(begin(), end(), __first, __last); }
+        { return *this = basic_string(__first, __last, get_allocator()); }

Reply via email to