- Qt中的字符串
- QLatinString
- 详细先容
- 源码
- 小结
- QStringLiteral(str)
- 详细先容
- 源码
- 小结
- QLatinString
Qt中的字符串
Qt中处置字符串最常用的肯定是QString,然则在qt creator源码中泛起了大量的QLatin1String。下面我们来先容下区别。
QLatinString
详细先容
我们首先来看QLatinString。类详细先容如下:
QString的许多成员函数都被重载以接受const char *而不是QString。 这包罗复制组织函数,赋值运算符,对照运算符以及种种其他函数,例如insert(),replace()和indexOf()。 这些函数通常经由优化,以制止为const char *数据组织QString工具。 例如,假设str是QString,
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工具并举行字符数据的深拷贝。
界说QT_NO_CAST_FROM_ASCII宏(如QString文档中所述)的应用程序无法访问QString的const char * 接口API。为了提供一种指定常量Latin-1字符串的有用方式,Qt提供了QLatin1String,它是const char *的异常薄的包装。使用QLatin1String,上面的示例代码变为
if (str == QLatin1String("auto")
|| str == QLatin1String("extern")
|| str == QLatin1String("static")
|| str == QLatin1String("register") {
...
}
键入的时间稍长一些,然则它提供的功能与代码的第一个版本完全相同,而且比使用QString::fromLatin1()转换Latin-1字符串的速率更快。
多亏了QString(QLatin1String)组织函数,QLatin1String可以在需要QString的任何地方使用。 例如:
QLabel *label = new QLabel(QLatin1String("MOD"), this);
注重:若是你挪用的函数,使用QLatin1String作为参数,实际上并未被重载来使用QLatin1String,而是举行QString的隐式转换,并将触发内存分配,而这是你通常使用QLatin1String首先要制止的情形。在这些情形下,使用QStringLiteral可能是更好的选择。
源码
我们看下QLatin1String源码,举行了截取,展现焦点部门
class QLatin1String
{
public:
inline QLatin1String() : m_size(0), m_data(nullptr) {}
inline explicit QLatin1String(const char *s) : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
private:
int m_size;
const char *m_data;
}
我们可以发现,真的是简朴的包装,也没有什么深拷贝什么的,只是把地址简朴的赋给了成员变量m_data。
小结
简朴说,QLatin1String就是对const char*的简朴包装,用在QT_NO_CAST_FROM_ASCII导致无法访问QString的const char*接口的地方。
QStringLiteral(str)
QString这个人人都很熟悉了,我们也不过多先容。这里提一下QStringLiteral,人人可以在QString类先容中找到。
详细先容
这是一个宏,在编译时从字符串文字str中为QString天生数据。 在这种情形下,可以免费建立QString,而且将天生的字符串数据存储在已编译目的文件的只读段中。
若是您的代码如下所示:
// hasAttribute takes a QString argument
if (node.hasAttribute("http-contents-length")) //...
然后这将建立一个暂且QString作为hasAttribute函数参数举行通报。 这可能会异常昂贵,由于它涉及内存分配以及将数据复制/转换为QString的内部编码。
通过使用QStringLiteral可以制止此成本:
if (node.hasAttribute(QStringLiteral(u"http-contents-length"))) //...
在这种情形下,QString的内部数据将在编译时天生。在运行时不会发生任何转换或分配。
使用QStringLiteral而不是用双引号引起来的纯C++字符串文字,可以显着加速凭据编译时已知的数据建立QString实例的速率。
注重:当将字符串通报给具有重载QLatin1String参数的函数时,QLatin1String仍比QStringLiteral更有用,而且此重载制止了转换为QString。例如,QString::operator ==()可以直接与QLatin1String举行对照:
if (attribute.name() == QLatin1String("http-contents-length")) //...
注重:某些编译器编码包罗US-ASCII字符集以外字符的字符串会有bug。在这种情形下,请确保在字符串前加上u
。否则是可选的。
源码
我们查看宏界说源码
template <int N>
struct QStaticStringData
{
QArrayData str;
qunicodechar data[N + 1];
QStringData *data_ptr() const
{
Q_ASSERT(str.ref.isStatic());
return const_cast<QStringData *>(static_cast<const QStringData*>(&str));
}
};
struct Q_CORE_EXPORT QArrayData
{
QtPrivate::RefCount ref;
int size;
uint alloc : 31;
uint capacityReserved : 1;
qptrdiff offset; // in bytes from beginning of header
}
#define QStringLiteral(str) \
([]() Q_DECL_NOEXCEPT -> QString { \
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
static const QStaticStringData<Size> qstring_literal = { \
Q_STATIC_STRING_DATA_HEADER_INITIALIZER(Size), \
QT_UNICODE_LITERAL(str) }; \
QStringDataPtr holder = { qstring_literal.data_ptr() }; \
const QString qstring_literal_temp(holder); \
return qstring_literal_temp; \
}())
#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
{ Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset }
#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER(size) \
Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, sizeof(QStringData))
我们对Q_STATIC_STRING_DATA_HEADER_INITIALIZER宏举行替换,可以获得
#define QStringLiteral(str) \
([]() Q_DECL_NOEXCEPT -> QString { \
// 盘算巨细,unicode为16bit一个字符,以是除2
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
// 焦点,只读静态变量,POD结构,编译器建立
static const QStaticStringData<Size> qstring_literal = { \
// QArrayData
{-1, \
size, \
0, \
0, \
sizeof(QStringData) \
}, \
// qunicodechar []
QT_UNICODE_LITERAL(str) }; \
// 获取编译器建立的静态底层数据
QStringDataPtr holder = { qstring_literal.data_ptr() }; \
// 组织QString,不用举行内存分配了
const QString qstring_literal_temp(holder); \
// 返回QString,完成加速
return qstring_literal_temp; \
}())
小结
说白了,QStringLiteral在编译期就建立了数据,制止了内存分配,加速了QString的建立。
原创造福人人,共享改变天下
献出一片爱心,温暖作者心灵
皇冠体育APP是一个开放皇冠代理APP下载、皇冠会员APP下载、皇冠线路APP下载、皇冠登录APP下载的平台,皇冠体育APP上最新登录线路、新2皇冠网址更新最快,皇冠体育APP开放皇冠会员注册、皇冠代理开户等业务。
网友评论
最新评论