在for循环中使用Qt字符串构建器

10

根据这篇这篇文档,我应该在for循环中使用QStringBuilder。应用它的代码如下:

QStringList words;
QString testString;

for (auto it = words.constBegin(); it != words.constEnd(); ++it)
{
    testString += "[" + *it + "] ";
}

然而我不明白怎么将其写成使用QStringBuilder的形式,因为我现在做的是一个赋值操作,但是根据文档,QStringBuilder要求我使用%运算符并且只进行一次赋值。


1
我会在QStringList中使用join方法:testString = words.join(" "); - Andrés Senac
我也会使用它,但我必须将每个单词用括号括起来。 - Stefano
3个回答

6
AFAICS 在这里, QStringBuilder 没有 %= 运算符。
然而,如果你想保留你的循环,你可以尝试像这样做:
#include <QStringBuilder>
#include <QStringList>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    QStringList words;
    words << "a1" << "a2" << "a3";
    QString testString;

    for (auto it = words.constBegin(); it != words.constEnd(); ++it)
    {
        testString = testString % *it % " ";
    }
    cout << testString.toStdString() << endl;
}

还有提到QT_USE_QSTRINGBUILDER宏,将所有+用法转换为%,前提是这不会在您的代码中其他地方引起问题。

编辑:

根据Marvin的评论,我认为我应该对我的回答进行一些澄清: 本答案展示了一种在循环中明确使用QStringBuilder和operator%的方法。 QStringBuilder是为了优化连接表达式而创建的,这种优化通过消除临时变量的需求,并计算连接字符串的总大小并同时分配它来实现(显然,这只能在表达式的“结尾”处完成)。

这意味着它的最佳使用可能不在循环中(例如上面的代码)。 但是,即使在这种情况下,它也可以给您一些优化,正如下面两个版本的gprof和Measure-Command输出所示。

版本1 - QStringBuilder和operator%(gprof累积秒:0.46; PowerShell Measure-Command:5:23s)

for (auto it = words.constBegin(); it != words.constEnd(); ++it)
{
    for (int i = 0; i < 100000; ++i)
    {
        testString = testString % *it % " ";
    }
}

版本2 - Qstring和operator+(gprof累计秒数:0.61;PowerShell Measure-Command:10:47s)

for (auto it = words.constBegin(); it != words.constEnd(); ++it)
{
    for (int i = 0; i < 100000; ++i)
    {
        testString = testString + *it + " ";
    }
}

因此,我认为使用QStringBuilder和operator%可能不会让您明显变差(请注意,上述值有点偏斜,除非您的应用程序实际上执行了数千次连接而没有任何I / O)。但是,像往常一样,由您来测量执行时间并决定哪种方法最适合您。

但是,如果testString = testString % *it,是否具有与文档中使用%相同的好处? - Stefano
@Stefano:今天早上我正在考虑这个问题(可能是在梦中想到的:D),并查看了源代码。它不会给你带来任何好处,因为QStringBuilder的operator%返回一个新的QStringBuilder。通过我的示例,可以确定,在每次迭代中都会构建一个QStringBuilder,从而破坏其惰性评估机制。据我所知,只有在同一表达式上有多个连接时,这才有用。 - PCaetano
:( 在这种情况下,QStringBuilder 是无用的。我想要一个类似于 C# 的字符串构建器。 - Stefano
@Stefano:是的。QStringBuilder和C#(以及Java)的StringBuilder之间的区别在于,前者不是用来显式实例化的,并且缺少Append()功能。另一方面,我怀疑(没有测量很难说)您的代码已经尽可能地高效了。在您的第一个Qt文档链接中,类似于您的代码,即使用operator+=的代码被描述为:“只有一个分配和一个复制,这是最佳的”。最后,如果这个循环不是瓶颈,我会把它留在原地。 - PCaetano
我不认为这会起作用。QStringBuilder通过使运算符%的返回值成为QStringBuilder而不是QString来实现其结果。当QStringBuilder被用于替换QString时,它会隐式地复制到新的QString中。您在每个循环迭代中将QStringBuilder从QString转换为QString,因此失去了真正字符串构建器的优势。 - Dirk Groeneveld

3
我认为只要你有这条线
DEFINES *= QT_USE_QSTRINGBUILDER

在您的.pro文件中,编译器将使用QStringBuilder来连接字符串。这在Qt 4.8及更高版本中有效。
编辑:Qt文档表示,该宏可能会导致您的项目不具备源代码兼容性。这篇文章article讨论了如何解决这个问题。基本上,您需要显式地将"+"表达式的结果转换为QString,例如使用QString(s1 + s2)而不是仅仅使用s1 + s2

我看到了那个宏,但文档还说它与源代码不兼容,并建议使用%运算符。 - Stefano
@Stefano:这篇文章:http://labs.qt.nokia.com/2011/06/13/string-concatenation-with-qstringbuilder/讲述了如何解决这个问题。它说你需要显式地将“+”表达式的结果转换为`QString`,例如使用`QString(s1 + s2)而不是仅仅使用s1 + s2`。 - TotoroTotoro

0

QString有一个方法reserve(),它允许提前保留更大的内存空间。例如,在循环中可以粗略估计结果字符串的大小时,这非常有用,因为它可以避免由于不断增长的字符串而导致的常量分配。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接