QStringLiteral、QLatin1String作用总结
1.QStringLiteral
这是一个宏定义,定义如下:
QStringLiteral(str)
该宏为字符串字面量在编译时期产生一个QString对象。产生的字符串数据存放在编译对象文件的只读片区。如果你写代码像下面那样:
// hasAttribute函数接受一个类型为QString的参数if (node.hasAttribute("http-contents-length")) //...
上面代码将会产生一个QString的临时对象,该临时对象作为参数传递给hasAttribute函数。这是非常昂贵的、效率非常低的操作。因为它涉及到内存分配、拷贝、转换字符串字面常量数据到QString内部编码等工作。通过QStringLiteral可以避免这种高代价操作。将上面代码改为如下:
if (node.hasAttribute(QStringLiteral(u"http-contents-length"))) //...
在这种情况下,QString内部数据将会在编译时期产生,而不是在每次运行时进行字符字面常量内存分配、字符字面量向QString对象的转换。
用QStringLiteral代替用双引号括起来的普通C++字符串字面常量,能够明显地提高从字符串字面常量创建QString对象实例的效率,且创建QString对象实例是在编译时进行的。
注意:当函数重载了QLatin1String参数时,调用重载QLatin1String类型的函数比QStringLiteral高效,因为它避免了转为QString,例如: QString::operator==() 能直接比较QLatin1String,如下:
if (attribute.name() == QLatin1String("http-contents-length"))
2.QLatin1String
QLatin1String类提供对基于US-ASCII/Latin-1 编码的字符串字面量的一层轻量封装。QString类有很多重载成员函数,这类函数被重载,以接受const char*参数,从而代替代替直接接受QString对象。这些重载函数包括:拷贝构造函数、比较操作符和其它函数,如 insert() 、replace()、 indexOf()。这些函数通常被优化,以避免从const char*构造出QString对象。类如,假想str是一个QString对象,如下代码:
if (str == "auto" || str == "extern"|| str == "static" || str == "register") {...}
比下面的代码效率高:
if (str == QString("auto") || str == QString("extern")|| str == QString("static") || str == QString("register")) {...}
因为后者不需要构造一个临时的QString对象,也不需对字符数据深度复制。
如果不想让应用程序访问、调用QString类中参数为const char*的系列函数,可以使用QT_NO_CAST_FROM_ASCII宏禁止C字符串字面量自动转为unicode编码的QString字符串。为了提供一种高效率地指定常量Latin-1编码的字符串方式,Qt提供QLatin1String类,该类是对const char*的一层轻量封装。上面的代码用QLatin1String改写为如下:
if (str == QLatin1String("auto")|| str == QLatin1String("extern")|| str == QLatin1String("static")|| str == QLatin1String("register") {...}
从类型来说,这有点长,但是它提供了和前文第一个版本同样的优点,且当转为Latin-1 编码时,比QString::fromLatin1()执行快。
多亏了以QLatin1String参数的QString的构造函数!在需要用QString的地方都可以QLatin1String,例如:
QLabel *label = new QLabel(QLatin1String("MOD"), this);
注意:如果用QLatin1String作为实参传给被调用函数,而被调用函数实际没有重载QLatin1String参数,即该函数的形参不是QLatin1String类型,这将导致隐式类型转换到QString,从而触发内存分配,这通常是我们想避免的,在这种情况下,用QStringLiteral替代QLatin1String是不错的选项。 也就是说如下函数:
void fun(const QString& str)
{// 其它代码
}
应优先采用
fun(QStringLiteral("csdn");
而不是采用
fun(QLatin1String("csdn");
而如果fun函数像如下那样:
void fun(const QLatin1String& str)
{// 其它代码
}
应优先采用:
fun(QLatin1String("csdn");