QArrayDataOps: fix appendUninitialized()
... to be strongly exception-safe and call placement new correctly. The old code could call user-provided overloads of new, because it didn't cast the pointer to void* before calling placement-new. It would also "randomly" stop when an exception was thrown. It correctly updated the size of the container only after successful construction of the element, but that's just weak exception-safety. There's no reason this operation shouldn't be strongly exception-safe. So instead of a raw loop around raw placement-new, use the corresponding raw memory STL algorithms. They handle exceptions and call placement-new correctly, and the code is both simpler as a consequence, and more efficient, as it updates this->size only once. Found in API-review. Amends 73bf1c1a9bcc2615370d6a199420da0c6f380a44. Change-Id: I535f393a3c378e1eea104bd3a05a274b9ec17964 Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit f699248c0f3ad44f09a422304870f40c1998a1a5) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
ea1978c7f9
commit
e6fc32a9c5
@ -969,15 +969,14 @@ public:
|
||||
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);
|
||||
T *const b = this->begin() + this->size;
|
||||
T *const e = this->begin() + newSize;
|
||||
if constexpr (std::is_constructible_v<T, Qt::Initialization>)
|
||||
std::uninitialized_fill(b, e, Qt::Uninitialized);
|
||||
else
|
||||
std::uninitialized_default_construct(b, e);
|
||||
this->size = newSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user