summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2023-10-31 14:05:29 +0100
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2024-02-16 14:20:50 +0100
commit73bf1c1a9bcc2615370d6a199420da0c6f380a44 (patch)
tree1149bd05cbd874ef008279e20883f9e27b8e6e8c /src/corelib/tools
parent277d77029d7fe8f46c6ee101869dcff389426cb1 (diff)
QList: add uninitialized resizes
Creating a QList of a given size, or resizing it to a given size, will always value-initialize its elements. This commit adds support for uninitialized construction and resizes. The intended use case is using a QList as storage-to-be-overwritten: QList<int> list(size, Qt::Uninitialized); fillWithData(list.data(), list.size); How do we define "uninitialized": 1) if T is constructible using Qt::Uninitialized, use that; 2) otherwise, default-construct T. In detail: 1) covers (Qt-ish) datatypes that have a default constructor that initializes them, but also a dedicated constructor that doesn't initialize (e.g. QPoint, QQuaternion, ...). 2) covers everything else. Default initialization of scalars and trivially constructible datatypes will leave them uninitialized. A type which isn't trivially constructible will still get its default constructor called (and possibly actually gets initialized); we can't really do better than that, as we still have to construct objects and start their lifetimes. [ChangeLog][QtCore][QList] Added support for uninitialized construction and resizing. Change-Id: I32c285c7dddbf7e01475943f24e14e824bb13090 Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools')
-rw-r--r--src/corelib/tools/qarraydataops.h19
-rw-r--r--src/corelib/tools/qlist.h14
-rw-r--r--src/corelib/tools/qlist.qdoc36
3 files changed, 69 insertions, 0 deletions
diff --git a/src/corelib/tools/qarraydataops.h b/src/corelib/tools/qarraydataops.h
index 78b0107655..c3e9821e81 100644
--- a/src/corelib/tools/qarraydataops.h
+++ b/src/corelib/tools/qarraydataops.h
@@ -7,6 +7,7 @@
#include <QtCore/qarraydata.h>
#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qnamespace.h>
#include <memory>
#include <new>
@@ -960,6 +961,24 @@ public:
// b might be updated so use [b, n)
this->copyAppend(b, b + n);
}
+
+ void appendUninitialized(qsizetype newSize)
+ {
+ Q_ASSERT(this->isMutable());
+ Q_ASSERT(!this->isShared());
+ Q_ASSERT(newSize > this->size);
+ Q_ASSERT(newSize - this->size <= this->freeSpaceAtEnd());
+
+ T *const b = this->begin();
+ do {
+ auto ptr = b + this->size;
+
+ if constexpr (std::is_constructible_v<T, Qt::Initialization>)
+ new (ptr) T(Qt::Uninitialized);
+ else
+ new (ptr) T; // not T() -- default-construct
+ } while (++this->size != newSize);
+ }
};
} // namespace QtPrivate
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index a0f29aadf6..684922cf08 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -10,6 +10,7 @@
#include <QtCore/qhashfunctions.h>
#include <QtCore/qiterator.h>
#include <QtCore/qcontainertools_impl.h>
+#include <QtCore/qnamespace.h>
#include <functional>
#include <limits>
@@ -324,6 +325,13 @@ public:
inline explicit QList(const String &str)
{ append(str); }
+ QList(qsizetype size, Qt::Initialization)
+ : d(size)
+ {
+ if (size)
+ d->appendUninitialized(size);
+ }
+
// compiler-generated special member functions are fine!
void swap(QList &other) noexcept { d.swap(other.d); }
@@ -404,6 +412,12 @@ public:
if (size > this->size())
d->copyAppend(size - this->size(), c);
}
+ void resizeForOverwrite(qsizetype size)
+ {
+ resize_internal(size);
+ if (size > this->size())
+ d->appendUninitialized(size);
+ }
inline qsizetype capacity() const { return qsizetype(d->constAllocatedCapacity()); }
void reserve(qsizetype size);
diff --git a/src/corelib/tools/qlist.qdoc b/src/corelib/tools/qlist.qdoc
index 5596813505..bf0f52eb6b 100644
--- a/src/corelib/tools/qlist.qdoc
+++ b/src/corelib/tools/qlist.qdoc
@@ -247,6 +247,31 @@
\sa resize()
*/
+/*! \fn template <typename T> QList<T>::QList(qsizetype size, Qt::Initialization)
+ \since 6.8
+
+ Constructs a list with an initial size of \a size elements.
+
+ QList will make an attempt at \b{not initializing} the elements.
+
+//! [qlist-uninitialized-strategy]
+ Specifically:
+
+ \list
+
+ \li if \c{T} has a constructor that accepts \c{Qt::Uninitialized},
+ that constructor will be used to initialize the elements;
+
+ \li otherwise, each element is default constructed. For
+ trivially constructible types (such as \c{int}, \c{float}, etc.)
+ this is equivalent to not initializing them.
+
+ \endlist
+//! [qlist-uninitialized-strategy]
+
+ \sa resizeForOverwrite()
+*/
+
/*! \fn template <typename T> QList<T>::QList(qsizetype size, parameter_type value)
Constructs a list with an initial size of \a size elements.
@@ -444,6 +469,17 @@
\sa size()
*/
+/*! \fn template <typename T> void QList<T>::resizeForOverwrite(qsizetype size)
+ \since 6.8
+
+ Sets the size of the list to \a size. If \a size is less than the
+ current size, elements are removed from the end. If \a size is
+ greater than the current size, elements are added to the end; QList
+ will make an attempt at \b{not initializing} these new elements.
+
+ \include qlist.qdoc qlist-uninitialized-strategy
+*/
+
/*! \fn template <typename T> qsizetype QList<T>::capacity() const
Returns the maximum number of items that can be stored in the