QStringLiteral is a macro that allows you to create QString objects from string literals with little to no runtime overhead. However, its usage can be tricky especially in code that must compile with different compilers, like the Qt code itself. This blog post lists some guidelines to help you avoid the pitfalls.
QString is the ubiquitous representation for a Unicode string in Qt. A common source for a QString are literals hard-coded into the application. In Qt 4, any such creation of a QString from a literal required creating the QString object on the heap, and then translating the literal characters from its run-time character codec to UTF-16. Since Qt 5.0, QStringLiteral allows to avoid this overhead by creating the object and doing the conversion at compile time.
Enable C++11 in your project
QStringLiteral is only optimized if the C++ compiler both supports lambdas and unicode literals. This is the case for Microsoft Visual Studio 2010 and newer, but GCC and Clang need to be told that they should support all C++11 features. When using qmake, this can be achieved by
CONFIG += c++11
Without the features, QStringLiteral falls back to QString::fromUtf8().
Use QStringLiteral only if a QString needs to be created
This sounds trivial, but it’s not necessarily so. Some methods in the Qt API have overloads for either taking a QString, or a QLatin1String object. This is because Latin1 is simpler to parse than UTF-16, and therefore the QLatin1String version can be faster, and use less memory. This is worth remembering especially for some QString methods:
bool same = (str == QLatin1String("Hello"));
str.startsWith(QLatin1String("Hello"));
str += QLatin1String("World");
are more efficient than
bool same = (str == QStringLiteral("Hello"));
str.startsWith(QStringLiteral("Hello"));
str += QStringLiteral("World");
Do not use QStringLiteral for empty strings
Prefer
QString()
over
QStringLiteral("")
The default constructor for QString is cheaper in terms of both instructions and memory.
Avoid duplicated QStringLiterals
Avoid having multiple QStringLiterals with the same content. For plain literals and QLatin1String, compilers try to consolidate identical literals so that they are not duplicated. For QStringLiteral, identical strings cannot be merged.
String concatenation
Unfortunately Visual Studio does not implement concatenation for string literals in the way the C++11 standard says. That is, having multiple adjacent ” ” sections (e.g. useful to spread across multiple lines) won’t work:
// error C2308: concatenating mismatched strings
// Concatenating wide "Hello" with narrow "World"
QStringLiteral("Hello " "World");
Other Visual Studio bugs
There are also other bugs in older Visual Studio versions. Here are a few known ones:
// (Visual Studio 2010, 2012)
// error: C1001: An internal error has occurred in the compiler.
QString array[2] = { QStringLiteral("Hello"), QStringLiteral("World") };
// (Visual Studio 2010)
// C2587: 'holder' : illegal use of local variable as default parameter
static QString formattedAddress(const QString &address,
const QString &newLine = QStringLiteral(""))
{
// ...
}
Summary
QStringLiteral speeds up the creation of QStrings from literals, at the expense of bigger binary sizes. To make these optimizations it requires C++11 features. There are cases though where using QStringLiteral does not pay off: For Qt API that optionally takes a QLatin1String, and for empty strings.
If you use QStringLiteral you should avoid declaring the same literal in multiple places: This furthermore blows up the binary sizes. Also, QStringLiteral exposes some bugs in Visual Studio compilers.
Further reading
Olivier Goffart explains both the reasons and the implementation of QStringLiteral in his highly recommended QStringLiteral blog post. Thiago Macieira blogged about it too.
The post Qt Weekly #13: QStringLiteral appeared first on Qt Blog.