QVector: preserve capacity in clear()

This is what std::vector implementations usually do,
because it minimizes memory fragmentation and useless
allocations since no user will call clear() unless
she intends to append new data afterwards.

Fix calls to resize(0) that show how existing code
tried to work around the issue.

Adjust test. Port from QVERIFY(==) to QCOMPARE as a
drive-by.

[ChangeLog][QtCore][QVector] clear() now preserves
capacity. To shed capacity, call squeeze() or swap
with a default-constructed QVector object, see the
documentation for an example.

Change-Id: I9cebe611a97e027a89e821e64408a4741b31f1f6
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
This commit is contained in:
Marc Mutz 2016-02-16 15:24:38 +01:00
parent 85c2a128ef
commit a7885c9756
12 changed files with 31 additions and 21 deletions

View File

@ -286,7 +286,7 @@ void QEventDispatcherUNIXPrivate::markPendingSocketNotifiers()
}
}
pollfds.resize(0);
pollfds.clear();
}
int QEventDispatcherUNIXPrivate::activateSocketNotifiers()
@ -480,8 +480,8 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
if (!canWait || (include_timers && d->timerList.timerWait(wait_tm)))
tm = &wait_tm;
d->pollfds.clear();
d->pollfds.reserve(1 + (include_notifiers ? d->socketNotifiers.size() : 0));
d->pollfds.resize(0);
if (include_notifiers)
for (auto it = d->socketNotifiers.cbegin(); it != d->socketNotifiers.cend(); ++it)

View File

@ -2335,7 +2335,7 @@ QRegExpCharClass::QRegExpCharClass()
void QRegExpCharClass::clear()
{
c = 0;
r.resize(0);
r.clear();
n = false;
}

View File

@ -502,8 +502,19 @@
/*! \fn void QVector::clear()
Removes all the elements from the vector and releases the memory used by
the vector.
Removes all the elements from the vector.
\note Until Qt 5.6, this also released the memory used by
the vector. From Qt 5.7, the capacity is preserved. To shed
all capacity, swap with a default-constructed vector:
\code
QVector<T> v ...;
QVector<T>().swap(v);
Q_ASSERT(v.capacity() == 0);
\endcode
or call squeeze().
\sa squeeze()
*/
/*! \fn const T &QVector::at(int i) const

View File

@ -419,7 +419,7 @@ void QVector<T>::resize(int asize)
}
template <typename T>
inline void QVector<T>::clear()
{ *this = QVector<T>(); }
{ resize(0); }
template <typename T>
inline const T &QVector<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");

View File

@ -1020,10 +1020,8 @@ bool QXmlStreamReaderPrivate::parse()
prefix.clear();
qualifiedName.clear();
namespaceUri.clear();
if (publicNamespaceDeclarations.size())
publicNamespaceDeclarations.clear();
if (attributes.size())
attributes.resize(0);
publicNamespaceDeclarations.clear();
attributes.clear();
if (isEmptyElement) {
setType(QXmlStreamReader::EndElement);
Tag &tag = tagStack_pop();

View File

@ -375,7 +375,7 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e)
QKeySequence::SequenceMatch result = QKeySequence::NoMatch;
// We start fresh each time..
d->identicals.resize(0);
d->identicals.clear();
result = find(e);
if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) {
@ -448,7 +448,7 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifier
}
// Looking for new identicals, scrap old
d->identicals.resize(0);
d->identicals.clear();
bool partialFound = false;
bool identicalDisabledFound = false;

View File

@ -2166,7 +2166,7 @@ void Parser::init(const QString &css, bool isFile)
}
hasEscapeSequences = false;
symbols.resize(0);
symbols.clear();
symbols.reserve(8);
Scanner::scan(Scanner::preprocess(styleSheet, &hasEscapeSequences), &symbols);
index = 0;

View File

@ -1128,7 +1128,7 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle
delete c.custom;
}
undoState = 0;
undoStack.resize(0);
undoStack.clear();
if (emitSignals && undoCommandsAvailable)
emitUndoAvailable(false);
if (emitSignals && redoCommandsAvailable)

View File

@ -516,7 +516,7 @@ QVector<QRect> MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const Q
if (overlap >= maxOverlap || maxOverlap == -1) {
if (overlap > maxOverlap) {
maxOverlap = overlap;
result.resize(0);
result.clear();
}
result << srcRect;
}

View File

@ -200,7 +200,7 @@ void QMenuBarPrivate::updateGeometries()
if(itemsDirty) {
for(int j = 0; j < shortcutIndexMap.size(); ++j)
q->releaseShortcut(shortcutIndexMap.value(j));
shortcutIndexMap.resize(0); // faster than clear
shortcutIndexMap.clear();
const int actionsCount = actions.count();
shortcutIndexMap.reserve(actionsCount);
for (int i = 0; i < actionsCount; i++)

View File

@ -1141,7 +1141,7 @@ void QTextBrowser::clearHistory()
d->forwardStack.clear();
if (!d->stack.isEmpty()) {
QTextBrowserPrivate::HistoryEntry historyEntry = d->stack.top();
d->stack.resize(0);
d->stack.clear();
d->stack.push(historyEntry);
d->home = historyEntry.url;
}

View File

@ -734,10 +734,11 @@ void tst_QVector::clear() const
QVector<T> myvec;
myvec << SimpleValue<T>::at(0) << SimpleValue<T>::at(1) << SimpleValue<T>::at(2);
QVERIFY(myvec.size() == 3);
const auto oldCapacity = myvec.capacity();
QCOMPARE(myvec.size(), 3);
myvec.clear();
QVERIFY(myvec.size() == 0);
QVERIFY(myvec.capacity() == 0);
QCOMPARE(myvec.size(), 0);
QCOMPARE(myvec.capacity(), oldCapacity);
}
void tst_QVector::clearInt() const
@ -1945,7 +1946,7 @@ void tst_QVector::resizePOD() const
const int capacity = vector.capacity();
vector.resize(0);
vector.clear();
QCOMPARE(vector.size(), 0);
QVERIFY(vector.capacity() <= capacity);
}