关于QString、QLatin1String、QStringLiteral

编码过程中,会不可避免地涉及到字面字符串,很多时候大家都是直接使用,没有太多考虑转换和效率的问题。

如果调用的函数支持const char这样的参数,那么直接使用字面字符串没有问题,这种函数一般都是极为常用的函数才会提供const char这样的重载,比如QString的operator==、operator+等等。

如果存在接受QLatin1String的参数,那么就可以提供QLatin1String(“xxx”)这样的参数,因为QLatin1String基本上就是const char*的一层薄薄的封装,所以这样做的效率也是挺高的。

但是,在只接受QString参数的函数,无论我们给一个字面字符串或QLatin1String,都会隐式构造一个临时的QString对象,构造这个对象需要在栈上申请一定的内存空间,然后把字符串拷贝过去,如果这样的调用比较多,那还是一笔不小的开销。此时,我们可以使用QStringLiteral来减少这个开销。
QStringLiteral其实是一个宏,展开来就是一个lambda函数的调用,该lambda函数内部使用了一个只读的静态变量保存了QString对象内存布局的POD对象,让这份数据保存在了程序的.rodata段。
当代码运行到这的时候,实质就是对该lambda函数的调用,该函数返回了一个用上面所说的POD对象构造出来的QString对象,因为QString是隐式共享的,所以这里并没有发生前面所说的开销,就可以提高效率。
这里用下面的代码展示QStringLiteral展开来之后的样子,理解起来会更加容易:

o->setObjectName(QStringLiteral("MyObject"));
// 展开之后:
o->setObjectName(([]() {
        // 计算字面字符串的大小,减去1个null字符
        enum { Size = sizeof(u"MyObject")/2 - 1 };
 
        // 编译期就完成了这个初始化
        static const QStaticStringData<Size> qstring_literal =
        { { /* ref = */ -1,
            /* size = */ Size,
            /* alloc = */ 0,
            /* capacityReserved = */ 0,
            /* offset = */ sizeof(QStringData) },
          u"MyObject" };
 
         QStringDataPtr holder = { &qstring_literal.str };
         QString s(holder); // 调用QString(QStringDataPtr&)构造函数
         return s;
    }()) // 调用lambda函数
  );

总结:
1、支持const char*或者QLatin1String的地方使用对应的参数
2、需要QString的地方,如果该QString不会修改的话,那使用QStringLiteral
3、需要QString且该QString可能会被修改的话,还是直接使用QString或者隐式转换吧

ui.tableWidget_2->clear(); if (depID && depID != m_compDepID) { m_queryInfoModel2.setQuery(QString("SELECT * FROM game WHERE game_id = %1").arg(depID)); } else if (employeeID) { m_queryInfoModel2.setQuery(QString("SELECT * FROM game WHERE game_id = %1").arg(employeeID)); } else { m_queryInfoModel2.setQuery(QString("SELECT * FROM game")); } int rows = m_queryInfoModel2.rowCount(); int columns = m_queryInfoModel2.columnCount() ; QModelIndex index; //设置表格的行数、列数 ui.tableWidget_2->setRowCount(rows); ui.tableWidget_2->setColumnCount(columns); QStringList headers; headers << QStringLiteral("游戏ID") << QStringLiteral("游戏名称") << QStringLiteral("游戏说明") << QStringLiteral("种类ID") << QStringLiteral("游戏评论数") << QStringLiteral("游戏论坛ID") << QStringLiteral("游戏评论ID") << QStringLiteral("创建时间") << QStringLiteral("游戏热度值") << QStringLiteral("游戏上线情况"); ui.tableWidget_2->setHorizontalHeaderLabels(headers); ui.tableWidget_2->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { index = m_queryInfoModel2.index(i, j); QString strData = m_queryInfoModel2.data(index).toString(); QSqlRecord record = m_queryInfoModel2.record(i); QString strdepRecordName = record.fieldName(j); if (strdepRecordName == QLatin1String("departmentID")) { ui.tableWidget_2->setItem(i, j, new QTableWidgetItem(m_depNameMap.value(strData))); continue; } else if (strdepRecordName == QLatin1String("status")) { ui.tableWidget_2->setItem(i, j, new QTableWidgetItem(m_statusMap.value(strData))); continue; } else if (strdepRecordName == QLatin1String("online")) { ui.tableWidget_2->setItem(i, j, new QTableWidgetItem(m_onlineMap.value(strData))); continue; } ui.tableWidget_2->setItem(i, j, new QTableWidgetItem(strData)); } }
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值