From 7196bc5b22d5d37b1fd87a9b68f0eb2073b1fa3e Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 2 Nov 2026 09:29:52 +0100 Subject: [PATCH] iter_impl: keep the type-dependent initialization in the constructor The check is not needed for correctness (m_it is value-initialized), but without it GCC 13 generates slower iteration loops: a recursive walk over a parsed document takes 0.5-2.7 % longer (callgrind: +1.9 % instructions on twitter.json, +0.95 % on canada.json). Clang generates identical code either way. See the measurements in #6005. Signed-off-by: Niels Lohmann --- .../nlohmann/detail/iterators/iter_impl.hpp | 19 +++++++++++++++++-- single_include/nlohmann/json.hpp | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/nlohmann/detail/iterators/iter_impl.hpp b/include/nlohmann/detail/iterators/iter_impl.hpp index 1d46168ab..6e6cc0ef6 100644 --- a/include/nlohmann/detail/iterators/iter_impl.hpp +++ b/include/nlohmann/detail/iterators/iter_impl.hpp @@ -107,8 +107,23 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci explicit iter_impl(pointer object) noexcept : m_object(object) { JSON_ASSERT(m_object != nullptr); - // m_it is value-initialized: its iterators are singular, and the - // primitive iterator is in its "uninitialized" state + + // m_it is already value-initialized, so this is not needed for + // correctness; it is kept because GCC generates faster loops with it + // (iterating a parsed document is 0.5-2.7 % slower without it, #6005) + if (m_object->is_object()) + { + m_it.object_iterator = typename object_t::iterator(); + } + else if (m_object->is_array()) + { + m_it.array_iterator = typename array_t::iterator(); + } + else + { + // primitive (is_primitive(), including discarded) + m_it.primitive_iterator = primitive_iterator_t(); + } } /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index d743ecf31..18c3041a9 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -24063,8 +24063,23 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci explicit iter_impl(pointer object) noexcept : m_object(object) { JSON_ASSERT(m_object != nullptr); - // m_it is value-initialized: its iterators are singular, and the - // primitive iterator is in its "uninitialized" state + + // m_it is already value-initialized, so this is not needed for + // correctness; it is kept because GCC generates faster loops with it + // (iterating a parsed document is 0.5-2.7 % slower without it, #6005) + if (m_object->is_object()) + { + m_it.object_iterator = typename object_t::iterator(); + } + else if (m_object->is_array()) + { + m_it.array_iterator = typename array_t::iterator(); + } + else + { + // primitive (is_primitive(), including discarded) + m_it.primitive_iterator = primitive_iterator_t(); + } } /*!