Существует ли в C ++ стандартная библиотека шаблонов классов, которая обеспечивает эффективную функциональность конкатенации строк, аналогичную Cring StringBuilder или Java StringBuffer ?
c++
stl
string-concatenation
Андрей
источник
источник
std::ostringstream
.Ответы:
ЗАМЕТЬТЕ, что этот ответ недавно привлек к себе внимание. Я не защищаю это как решение (это решение, которое я видел в прошлом, до STL). Это интересный подход и должен применяться только по
std::string
илиstd::stringstream
если после профилирования кода вы обнаружите , что делает улучшение.Я обычно использую либо
std::string
илиstd::stringstream
. У меня никогда не было проблем с этим. Обычно я сначала резервирую номер, если заранее знаю приблизительный размер струны.Я видел, как в далеком прошлом другие люди создавали свои собственные оптимизированные струнные инструменты.
Он использует две строки, одну для большей части строки, а другую в качестве рабочей области для объединения коротких строк. Он оптимизирует операции добавления, объединяя короткие операции добавления в одну небольшую строку, затем добавляя ее в основную строку, тем самым уменьшая количество перераспределений, необходимых для основной строки, по мере ее увеличения.
Я не требовал этого трюка с
std::string
илиstd::stringstream
. Я думаю, что он использовался со сторонней библиотекой строк до std :: string, это было так давно. Если вы принимаете стратегию, подобную этой, ваше приложение будет первым.источник
scratch
строка действительно чего-то добивается здесь. Количество перераспределений основной строки в значительной степени будет зависеть от ее окончательного размера, а не от количества операций добавления, еслиstring
реализация не очень плохая (т. Е. Не использует экспоненциальный рост). Таким образом, «группировка»append
не помогает, потому что, если базовый размерstring
большой, он будет расти только изредка в любом случае. Кроме того, он добавляет кучу избыточных операций копирования и может перераспределять больше (следовательно, вызываетnew
/delete
), так как вы добавляете короткую строку.str.reserve(1024);
что будет быстрее, чем эта вещьC ++ способ будет использовать std :: stringstream или просто конкатенации строк. Строки C ++ являются изменяемыми, поэтому соображения производительности при объединении менее важны.
Что касается форматирования, вы можете выполнять одинаковое форматирование в потоке, но другим способом, аналогичным
cout
. или вы можете использовать строго типизированный функтор, который инкапсулирует это и предоставляет интерфейс, подобный String.Format, например boost :: formatисточник
StringBuilder
заключается в том, чтобы покрыть неэффективность неизменяемого базового типа String в Java . Другими словами,StringBuilder
это лоскутное одеяло, поэтому мы должны быть рады, что нам не нужен такой класс в C ++.O(n)
в общем случае.std::string.append
Функция не является хорошим вариантом , поскольку он не принимает много форм данных. Более полезной альтернативой является использованиеstd::stringstream
; вот так:источник
std::string
является эквивалентом C ++: он изменчив.источник
Вы можете использовать .append () для простого объединения строк.
Я думаю, что вы могли бы даже сделать:
Что касается операций форматирования в C #
StringBuilder
, я считаюsnprintf
(илиsprintf
если вы хотите рискнуть написать ошибочный код ;-)) в массив символов и преобразовать обратно в строку - это единственный вариант.источник
Поскольку
std::string
в C ++ изменчиво, вы можете использовать это. Это имеет+= operator
иappend
функция.Если вам нужно добавить числовые данные, используйте
std::to_string
функции.Если вам нужна еще большая гибкость в форме возможности сериализации любого объекта в строку, используйте
std::stringstream
класс. Но вам нужно будет реализовать свои собственные функции оператора потоковой передачи, чтобы он работал с вашими собственными классами.источник
std :: string's + = не работает с const char * (что вроде «строка для добавления» выглядит так), поэтому, безусловно, использование stringstream является наиболее близким к тому, что требуется - вы просто используете << вместо +
источник
Удобный конструктор строк для C ++
Как многие люди отвечали ранее, метод std :: stringstream является предпочтительным. Он работает хорошо и имеет много вариантов преобразования и форматирования. ИМО, однако, имеет один довольно неудобный недостаток: вы не можете использовать его как один вкладыш или как выражение. Вы всегда должны написать:
что довольно раздражает, особенно если вы хотите инициализировать строки в конструкторе.
Причина в том, что a) std :: stringstream не имеет оператора преобразования в std :: string и b) операторы << () строкового потока не возвращают ссылку на поток строки, а вместо этого ссылку на std :: ostream - который не может быть далее вычислен как поток строки.
Решением является переопределение std :: stringstream и предоставление ему более подходящих операторов:
С этим вы можете написать такие вещи, как
даже в конструкторе.
Я должен признаться, что я не измерял производительность, так как я еще не использовал ее в среде, которая интенсивно использует построение строк, но я предполагаю, что она не будет намного хуже, чем std :: stringstream, так как все сделано через ссылки (кроме преобразования в строку, но это также операция копирования в std :: stringstream)
источник
std::stringstream
так себя не ведет.Rope контейнер может быть стоит , если нужно вставить / удалить строку в случайное место строки назначения или для длинных последовательностей гольцов. Вот пример из реализации SGI:
источник
Я хотел добавить что-то новое из-за следующего:
С первой попытки мне не удалось победить
std::ostringstream
«soperator<<
эффективность, но с большим количеством попыток я смог сделать StringBuilder, который в некоторых случаях быстрее.
Каждый раз, когда я добавляю строку, я просто сохраняю ссылку на нее и увеличиваю счетчик общего размера.
Реальный способ, которым я наконец реализовал это (Ужас!), Состоит в том, чтобы использовать непрозрачный буфер (std :: vector <char>):
для байта []
для перемещенных струн (с добавленными струнами
std::move
)std::string
объект (у нас есть право собственности)для струнных
std::string
объект (без владения)Есть также одна небольшая оптимизация: если последняя вставленная строка была перемещена, она проверяет наличие свободных зарезервированных, но неиспользуемых байтов и сохраняет там дополнительные байты вместо использования непрозрачного буфера (это экономит некоторую память, фактически делает ее немного медленнее). , может зависеть также от процессора, и в любом случае редко можно увидеть строки с дополнительным зарезервированным пространством)
Это было, наконец, немного быстрее,
std::ostringstream
но у него есть несколько недостатков:ostringstream
вывод? использование
std::ostringstream
Это уже устранило самое большое узкое место, в то время как увеличение скорости на несколько% при реализации шахты не стоит минусов.
источник