【问题标题】:Qt string builder in for loopfor循环中的Qt字符串生成器
【发布时间】:2012-08-29 21:43:42
【问题描述】:

按照 thisthis 文档,我将在 for 循环中使用 QStringBuilder。我应该应用它的代码是

QStringList words;
QString testString;

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

但是我不明白如何编写它来使用 QStringBuilder,因为我在这里做一个赋值,而不是 QStringBuilder 要求我使用 % 运算符并且只在文档之后做一个赋值。

【问题讨论】:

  • 我会使用QStringList中的join方法:testString = words.join(" ");
  • 我也会使用它,但我必须将每个单词括在括号内

标签: c++ qt4 stringbuilder qstring


【解决方案1】:

AFAICS here,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 % *它是否与在文档中使用 % 具有相同的好处?
  • @Stefano:我今天早上实际上正在考虑这个问题(一定是在睡梦中考虑过这个问题:D),并查看了来源。它不会给你带来任何好处,因为 QStringBuilder 的 operator% 返回一个新的 QStringBuilder。通过我的示例,果然,它在每次迭代时都构建了一个 QStringBuilder,从而打败了它的惰性求值机制。据我所知,这只有在同一个表达式上有多个连接时才有用。
  • :( QStringBuilder 在这种情况下没用。我想要一种像 C# 这样的字符串生成器
  • @Stefano:是的。 QStringBuilder 和 C#(和 Java)的 StringBuilder 之间的区别在于前者并不意味着显式实例化,并且缺少 Append() 功能。 OTOH,我怀疑(很难说没有测量)您的代码已经尽可能高效。在您的第一个 Qt Docs 链接上,与您的代码类似的代码,即使用 operator+= 的描述如下:“只有一个分配和一个副本,这是最佳的”。最后,如果这个循环不是瓶颈,我就让它保持原样。
  • 我认为这行不通。 QStringBuilder 通过使 operator% 的返回值为 QStringBuilder 而不是 QString 来实现其结果。当 QStringBuilder 被用来代替 QString 时,它被隐式复制到一个新的 QString 中。您在每次循环迭代中都从 QStringBuilder 转换为 QString,因此您失去了真正的字符串构建器的优势。
【解决方案2】:

我想只要你有行

DEFINES *= QT_USE_QSTRINGBUILDER

在您的 .pro 文件中,编译器将使用 QStringBuilder 来连接字符串。这适用于 Qt 4.8 及更高版本。

编辑:Qt 文档说这个宏可能会使您的项目与源代码不兼容。这个article 谈论如何解决这个问题。基本上,您需要将“+”表达式的结果显式转换为QString,例如使用QString(s1 + s2) 而不仅仅是s1 + s2

【讨论】:

  • 我看到了那个宏,但文档也说它的源不兼容并建议使用 % 运算符
  • @Stefano:这篇文章:labs.qt.nokia.com/2011/06/13/… 讨论了如何解决这个问题。它说您需要将“+”表达式的结果显式转换为QString,例如使用QString(s1 + s2) 而不仅仅是s1 + s2
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-01
    相关资源
    最近更新 更多