Правильный способ конвертировать (много!) Чисел в строки без выделения в Qt

Я хочу позвонить QString::number(int) много раз в секунду. Это очень медленно: кажется, что каждый раз выделяется новая строка. Пытался использовать setNum вместо этого на одной струне все еще нет радости.


Оригинальный, длинный вопрос:

Эта проблема

У меня есть большой массив чисел (скажем, целых чисел), и я хочу отформатировать их в текст, который затем (возможно, не сразу) будет записан в файл. Наивный способ выглядит примерно1 как это:

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

Это занимает около 280ms за 150000 целые числа на моей машине, что мне кажется очень много. Я полагаю, что это потому, что QString::number вызывается 150000 раз и каждый раз выделяет новую строку. Это каким-то образом подтверждается, что корень проблемы, когда я пытаюсь использовать itoa (который не выделяет память) вместо этого.

Возможно, но не Qt [not-cute] решение

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

Это занимает около 70ms для того же 150000 целые числа (о 4x быстрее), что сейчас приемлемо для меня (Я думаю, что я могу сделать что-то и с конкатенацией строк, но давайте оставим это вне этого вопроса)

Но Мне не нравится, что я должен использовать некоторые нестандартные, вероятно, устаревшие, вероятно, не переносимые2 функция (не сказать, что это выглядит просто уродливо).

Тогда я вспомнил, что есть также пример метод: QString::setNum. Я надеялся, что смогу использовать тот же шаблон, что и с itoa: выделите только одну строку и изменяйте ее каждый раз.

Желательно, но не работает решение

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

К сожалению, это не имеет большого значения от QString::number: опять около 280мс, ну может быть 250мс но все равно слишком много.

Итак, поздравляю, если вы достигли здесь 🙂 и, наконец, …

  1. Какие эксперты Qt посоветуют мне сделать? Заткнись и используй itoa несмотря на отчетливый запах C в другом ароматном C ++ / Qt-коде?
  2. Или я могу как-то сказать «Да ладно, Qstring, просто есть этот номер в вас» ?
  3. Я думаю Зачем setNum не сделал трюк?

Примечания:

1 В реальном коде у меня есть не только 150000 целых чисел, но 50000 троек целых чисел, которые я также добавляю '\t' между ними. Это единственное отличие от моего реального кода, и я думаю, что это не важно: здесь меня интересует только производительность QString::number против itoa,

2 На самом деле, я был удивлен, что MinGW также имеет _itoa_s он ведет себя так же, как и Visual Studio, но у меня все еще есть какое-то неловкое ощущение, что использование такой грязной функции в моем отшлифованном коде Qt уменьшает его переносимость. Поправьте меня если я ошибаюсь.

7

Решение

Вы можете попробовать использовать QByteArray, который использует тот же интерфейс QString, но больше подходит для проблем с производительностью. Я получаю 36 мс (qt 5.2 clang) против ваших исходных 57 мс (на моей машине) с этим кодом:

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

и 29 мс с этой версией (что может подтвердить ваши предположения о setNum):

QByteArray allDatad;
QByteArray number;
foreach(const int & value, values) {
number.setNum(value);
allDatad += number;
allDatad += '\n';
}
5

Другие решения

Как насчет использования STL?

Я проверил ваш код (изменив цикл для упрощения)

int main() {
stringstream ss;
for(int i=0; i<2000000; ++i) {
ss << i << "\n";
}
}

И я получаю

time ./ss_test
real  0m0.146s
user  0m0.139s
sys   0m0.006s

С версией Qt (на моей машине)

int main() {
QString allData;
for(int i=0; i<2000000; ++i) {
allData += QString::number(i);
allData += '\n';
}
}

Я получаю

time ./qtstring_test
real 0m0.516s
user 0m0.508s
sys  0m0.008s
3

По вопросам рекламы [email protected]