https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121946
--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to Marc Glisse from comment #2) > If I make __is_bitwise_relocatable<int> false, we don't get memmove/memcpy > for foo_int either. If we didn't use __relocate at all, we'd also get memcpy. Because we'd relocate with std::uninitialized_move followed by std::destroy_n. On paper that means two loops, but because the destructor is trivial, destroy_n is a no-op. And the uninitialized_move would be optimized to memcpy. So the relocate "optimization" hurts here. The __relocate optimization makes sense for types that are actually bitwise relocatable, and for types that are not trivially destructible, but for this case we'd be better off with: --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -1267,6 +1267,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ValueType2; static_assert(std::is_same<_ValueType, _ValueType2>::value, "relocation is only possible for values of the same type"); + + if _GLIBCXX_CONSTEXPR (__is_trivially_destructible(_ValueType)) + { + __result = std::uninitialized_move(__first, __last, __result); + std::_Destroy(__first, __last); // will be optimized away + return __result + } + _ForwardIterator __cur = __result; for (; __first != __last; ++__first, (void)++__cur) std::__relocate_object_a(std::addressof(*__cur), Or we could just change the definition of __bitwise_relocatable.