在Qt中没有分配的情况下将(多个!)数字转换为字符串的正确方法

NIA*_*NIA 7 c++ performance qstring qt itoa

TL;博士

我想QString::number(int)每秒多次打电话.它非常慢:似乎每次都分配一个新的字符串.尝试使用setNum相同的字符串代替,仍然没有喜悦.


原来的长问题:

问题

我有一大堆数字(比如整数),我想将它们格式化为文本,然后(可能不会立即)写入文件.天真的方式看起来像这样大约1:

QString allData;
foreach(const int & value, values) {
    allData += QString::number(value);
    allData += '\n';
}
Run Code Online (Sandbox Code Playgroud)

我机器上的150000整数需要大约280ms,这对我来说似乎很重要.我想这是因为被调用150000次并且每次都分配新的字符串.当我尝试使用(不分配内存)时,这被证实是问题的根源.QString::numberitoa

可能,但不是Qt [not-cute]解决方案

QString allData;
char buffer[100];                               // <-------
foreach(const int & value, values) {
    _itoa_s(value, buffer, sizeof(buffer), 10); // <-------
    allData += buffer;
    allData += '\n';
}
Run Code Online (Sandbox Code Playgroud)

对于相同的150000个整数(大约快4倍),这需要大约70ms,这对我来说是现在可以接受的(我想我也可以使用字符串连接做一些事情,但是让我们把它留在这个问题之外)

我不喜欢我必须使用一些不标准的,可能已被弃用的,可能是不可移植的2功能(并不是说这看起来很难看).

然后我记得还有一个实例方法:QString::setNum.我希望我可以使用与以下相同的模式itoa:只分配一个字符串并每次修改它.

可取的,但不工作的解决方案

QString allData;
QString number;                       // <-------
foreach(const int & value, values) {
    number.setNum(value);             // <-------
    allData += number;
    allData += '\n';
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这并没有太大的区别QString::number:再大约280ms,好吧,也许250ms但仍然太多.

所以,恭喜你到达这里:)最后......

问题

  1. 什么将Qt的专家建议我做的itoa尽管在其他芳香的C++/Qt代码中有明显的C气味但闭嘴并使用?
  2. 或者我可以以某种方式说"来吧,Qstring,只是把这个号码给你"
  3. 我想知道为什么setNum不做这个伎俩

脚注:

1在实际代码中,我不仅有150000个整数,还有50000个整数三元组,我也在'\t'它们之间添加.这是我实际代码的唯一区别,我想这并不重要:这里我只对QString::numbervs的性能感兴趣itoa.

2实际上,我很惊讶MinGW的_itoa_s行为就像Visual Studio一样,但我仍有一些尴尬的感觉,在我的抛光Qt代码中使用这样一个脏函数会降低其可移植性.如我错了请纠正我.

Sal*_*nzo 5

您可以尝试使用QByteArray共享相同的QString接口,但更适合性能问题.我使用此代码获得36 ms(qt 5.2 clang)与原始57 ms(在我的机器上):

QByteArray allDatab;
foreach(const int & value, values) {
    allDatab += QByteArray::number(value);
    allDatab += '\n';
}
QString result(allDatab);
Run Code Online (Sandbox Code Playgroud)

此版本的29毫秒(可能确认您对setNum的假设):

QByteArray allDatad;
QByteArray number;                       
foreach(const int & value, values) {
    number.setNum(value);             
    allDatad += number;
    allDatad += '\n';
}
Run Code Online (Sandbox Code Playgroud)