Using QString Effectively: Difference between revisions
Lord Drako (talk | contribs) |
(clean-up) |
||
(4 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:QtInternals]] | [[Category:QtInternals]] | ||
Written By : Girish Ramakrishnan, ForwardBias Technologies | Written By : Girish Ramakrishnan, ForwardBias Technologies | ||
Line 14: | Line 8: | ||
Creating a QString from a C-string may involve a malloc. For example, there is possibly a hidden-malloc cost in the following code. | Creating a QString from a C-string may involve a malloc. For example, there is possibly a hidden-malloc cost in the following code. | ||
<code> | <code> | ||
if (fruit == "apple") { | if (fruit == "apple") { ... } // possibly hidden malloc | ||
</code> | </code> | ||
QString provides a QString::operator==(const char *) overload for comparison with C-strings. As explained in [ | QString provides a QString::operator==(const char *) overload for comparison with C-strings. As explained in [[QtStrings | QtString]], the encoding of C-strings is determined using QTextCodec::setCodecForCStrings(). When no special encoding is set, Qt performs the above comparison by providing a specialized function that compares a Unicode string (fruit) and the Latin-1 string ('apple'). This comparison is fast and requires no mallocs. | ||
However, when QTextCodec::setCodecForCString is set, "apple" gets converted into a QString using QString::fromAscii(). This means that QString will allocate memory for the string "apple" and creates a deep copy of the C-style string before performing the comparison! | However, when QTextCodec::setCodecForCString is set, "apple" gets converted into a QString using QString::fromAscii(). This means that QString will allocate memory for the string "apple" and creates a deep copy of the C-style string before performing the comparison! | ||
Line 25: | Line 19: | ||
Since comparisons with Latin-1 C-strings are very common in programs, Qt provides a special class called QLatin1String that just holds a pointer to a Latin-1 encoded C-string. In addition, QString provides a QString::operator(const QLatin1String &) overload that calls the specialized function that compares the Unicode string and Latin1-string. We can make the above code assuredly fast by writing it instead as, | Since comparisons with Latin-1 C-strings are very common in programs, Qt provides a special class called QLatin1String that just holds a pointer to a Latin-1 encoded C-string. In addition, QString provides a QString::operator(const QLatin1String &) overload that calls the specialized function that compares the Unicode string and Latin1-string. We can make the above code assuredly fast by writing it instead as, | ||
<code> | <code> | ||
if (fruit QLatin1String("apple")) { … } // fast and mentions encoding | if (fruit == QLatin1String("apple")) { … } // fast and mentions encoding | ||
</code> | </code> | ||
Line 45: | Line 39: | ||
</code> | </code> | ||
The additional mallocs can be avoided if the length of the final QString is known in advance. Qt 4.6 introduces an internal class called QStringBuilder that "reserves" memory for a concatenation chain in a single shot. It does so by having each of the + operations above return a different class (not QString anymore). This class keeps track of the string's that are being appended and the required memory at each step. At the final step, when the concatenation operation gets converted into a QString it allocates memory in a single shot and copies all the strings in the chain one after another. This feature can be enabled by including <QtCore/QStringBuilder> and using the operator% instead of {{#tag:syntaxhighlight|{{{|operator +}}}|lang={{{lang|cpp}}}|enclose=none}}. One would now write, | The additional mallocs can be avoided if the length of the final QString is known in advance. Qt 4.6 introduces an internal class called QStringBuilder that "reserves" memory for a concatenation chain in a single shot. It does so by having each of the + operations above return a different class (not QString anymore). This class keeps track of the string's that are being appended and the required memory at each step. At the final step, when the concatenation operation gets converted into a QString it allocates memory in a single shot and copies all the strings in the chain one after another. This feature can be enabled by including <QtCore/QStringBuilder> and using the {{#tag:syntaxhighlight|{{{|operator %}}}|lang={{{lang|cpp}}}|enclose=none}} instead of {{#tag:syntaxhighlight|{{{|operator +}}}|lang={{{lang|cpp}}}|enclose=none}}. One would now write, | ||
<code> | <code> | ||
if (foo.startsWith("(" % type % ")")) | if (foo.startsWith("(" % type % ")")) | ||
</code> | </code> | ||
{{#tag:syntaxhighlight|{{{|operator +}}}|lang={{{lang|cpp}}}|enclose=none}} can be used instead of {{#tag:syntaxhighlight|{{{|operator %}}}|lang={{{lang|cpp}}}|enclose=none}} by defining QT_USE_QSTRINGBUILDER. See [http:// | {{#tag:syntaxhighlight|{{{|operator +}}}|lang={{{lang|cpp}}}|enclose=none}} can be used instead of {{#tag:syntaxhighlight|{{{|operator %}}}|lang={{{lang|cpp}}}|enclose=none}} by defining QT_USE_QSTRINGBUILDER. See [http://doc.qt.io/qt-5/qstring.html#more-efficient-string-construction Fast concatenation] for more details. | ||
= QStringMatcher : Fast string matching = | = QStringMatcher : Fast string matching = |
Latest revision as of 16:00, 24 March 2016
Written By : Girish Ramakrishnan, ForwardBias Technologies
This page explains the purpose of various QString related classes.
Creating a QString from a C-string may involve a malloc. For example, there is possibly a hidden-malloc cost in the following code.
if (fruit == "apple") { ... } // possibly hidden malloc
QString provides a QString::operator==(const char *) overload for comparison with C-strings. As explained in QtString, the encoding of C-strings is determined using QTextCodec::setCodecForCStrings(). When no special encoding is set, Qt performs the above comparison by providing a specialized function that compares a Unicode string (fruit) and the Latin-1 string ('apple'). This comparison is fast and requires no mallocs.
However, when QTextCodec::setCodecForCString is set, "apple" gets converted into a QString using QString::fromAscii(). This means that QString will allocate memory for the string "apple" and creates a deep copy of the C-style string before performing the comparison!
Application developers set QTextCodec::setCodecForCString() in main() without realizing that this has the side-effect of a malloc for every single C-style string comparison.
Since comparisons with Latin-1 C-strings are very common in programs, Qt provides a special class called QLatin1String that just holds a pointer to a Latin-1 encoded C-string. In addition, QString provides a QString::operator(const QLatin1String &) overload that calls the specialized function that compares the Unicode string and Latin1-string. We can make the above code assuredly fast by writing it instead as,
if (fruit == QLatin1String("apple")) { … } // fast and mentions encoding
In Qt's own code, all C-strings comparisons use QLatin1String since the application can choose an arbitrary codec for C-strings.
QStringRef : String manipulation without the malloc
QString has various methods for string manipulations like mid(), left(), right(). All of them create a new QString and hence a malloc/deep copy of data in an existing QString. Instead, QString::midRef(), QString::leftRef() and QString::rightRef() can be used to obtain a QStringRef. A QStringRef is a reference of a portion of a QString. QString also provides many overloads like QString::operator==(const QStringRef &) for optimal use with QStringRef.
QString::reserve and QString::squeeze
It's better to call QString::reserve to allocate extra memory in advance so that every call to QString::append() does not result in a malloc. Extra memory can be reclaimed using QString::squeeze.
QStringBuilder : Fast QString concatenation
The code below requires atleast 2 mallocs. First a malloc to store the result of "(" + type. And then another malloc for appending the ")". The number of mallocs increases with each addition of operator +
.
if (foo.startsWith("(" + type + ")"))
The additional mallocs can be avoided if the length of the final QString is known in advance. Qt 4.6 introduces an internal class called QStringBuilder that "reserves" memory for a concatenation chain in a single shot. It does so by having each of the + operations above return a different class (not QString anymore). This class keeps track of the string's that are being appended and the required memory at each step. At the final step, when the concatenation operation gets converted into a QString it allocates memory in a single shot and copies all the strings in the chain one after another. This feature can be enabled by including <QtCore/QStringBuilder> and using the operator %
instead of operator +
. One would now write,
if (foo.startsWith("(" % type % ")"))
operator +
can be used instead of operator %
by defining QT_USE_QSTRINGBUILDER. See Fast concatenation for more details.