https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96088
--- Comment #1 from François Dumont <fdumont at gcc dot gnu.org> --- The core issue here is that unordered_map key type is std::string while you insert const char* which explains the temporary. In f2 you use insert(Pair&&) method so a temporary is generated but then moved into the container. In f1 we try to check for insertion before generating the value_type and to do so we use hash<std::string> that generates an additional temporary. I'll check if we can be smarter here. A nice improvement would be to change std::hash<std::string> operator signature to: size_t operator()(const string_view& __str) const noexcept but that's a Standard modification.