Containers: call constructors even for primitive types
Trivial types are automatically classified as Q_PRIMITIVE_TYPE, but it doesn't mean that they can be initialized with memset(0) (notably, pointers to data members on Itanium ABIs are initialized with -1, not 0). Drop that kind of optimization, and always value-initialize objects in containers. Fix the documentation to match as well. This is a rework of f6f68409a40beaa5f034c411dd7e296c7828d8fd and 82b13880b994ff9b87710e0729e32035ab3b63a4 in Qt 6. [ChangeLog][QtCore][QTypeInfo] The semantics of Q_PRIMITIVE_TYPE have been slightly changed. Qt now value-initializes types marked as primitive (which, by default, include trivial types) instead of simply using memset(0), which is wrong in some corner cases. Change-Id: Ib61396be883424e2f03a9f3bbce1eaddce6aa731 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit 76671a57b5418ec98fe2c94a963728ac3306dc82) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
28b015342d
commit
0943ad0241
@ -4030,10 +4030,8 @@ bool qunsetenv(const char *varName)
|
||||
|
||||
\list
|
||||
\li \c Q_PRIMITIVE_TYPE specifies that \a Type is a POD (plain old
|
||||
data) type with no constructor or destructor, or else a type where
|
||||
every bit pattern is a valid object; memset()ting memory to zero
|
||||
creates a value-initialized instance of the type; and memcpy()ing
|
||||
creates a valid independent copy of an object.
|
||||
data) type with no constructor or destructor, and for which memcpy()ing
|
||||
creates a valid independent copy of the object.
|
||||
\li \c Q_MOVABLE_TYPE specifies that \a Type has a constructor
|
||||
and/or a destructor but can be moved in memory using \c
|
||||
memcpy(). Note: despite the name, this has nothing to do with move
|
||||
|
@ -65,8 +65,10 @@ struct QPodArrayOps
|
||||
Q_ASSERT(newSize > uint(this->size));
|
||||
Q_ASSERT(newSize <= this->alloc);
|
||||
|
||||
::memset(static_cast<void *>(this->end()), 0, (newSize - this->size) * sizeof(T));
|
||||
this->size = int(newSize);
|
||||
T *const begin = this->begin();
|
||||
do {
|
||||
new (begin + this->size) T();
|
||||
} while (uint(++this->size) != newSize);
|
||||
}
|
||||
|
||||
void copyAppend(const T *b, const T *e)
|
||||
@ -154,7 +156,7 @@ struct QGenericArrayOps
|
||||
|
||||
T *const begin = this->begin();
|
||||
do {
|
||||
new (begin + this->size) T;
|
||||
new (begin + this->size) T();
|
||||
} while (uint(++this->size) != newSize);
|
||||
}
|
||||
|
||||
|
@ -323,13 +323,8 @@ private:
|
||||
template <typename T>
|
||||
void QVector<T>::defaultConstruct(T *from, T *to)
|
||||
{
|
||||
if (QTypeInfo<T>::isComplex) {
|
||||
while (from != to) {
|
||||
new (from++) T();
|
||||
}
|
||||
} else {
|
||||
::memset(static_cast<void *>(from), 0, (to - from) * sizeof(T));
|
||||
}
|
||||
while (from != to)
|
||||
new (from++) T();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -599,17 +594,13 @@ void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::Allo
|
||||
|
||||
if (asize > d->size) {
|
||||
// construct all new objects when growing
|
||||
if (!QTypeInfo<T>::isComplex) {
|
||||
::memset(static_cast<void *>(dst), 0, (static_cast<T *>(x->end()) - dst) * sizeof(T));
|
||||
} else {
|
||||
QT_TRY {
|
||||
while (dst != x->end())
|
||||
new (dst++) T();
|
||||
} QT_CATCH (...) {
|
||||
// destruct already copied objects
|
||||
destruct(x->begin(), dst);
|
||||
QT_RETHROW;
|
||||
}
|
||||
QT_TRY {
|
||||
while (dst != x->end())
|
||||
new (dst++) T();
|
||||
} QT_CATCH (...) {
|
||||
// destruct already copied objects
|
||||
destruct(x->begin(), dst);
|
||||
QT_RETHROW;
|
||||
}
|
||||
}
|
||||
} QT_CATCH (...) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user