На самом деле вы не можете сформировать std :: string без копирования данных. Поток строк, вероятно, будет повторно использовать память от прохода к проходу (хотя я думаю, что стандарт ничего не говорит о том, должен ли он на самом деле), но он все равно не избежит копирования.
Распространенным подходом к решению этой проблемы является написание кода, который обрабатывает данные на шаге 3 для использования пары итератор начала / конца; затем он может легко обрабатывать либо std :: string, вектор символов, пару необработанных указателей и т. д. В отличие от передачи ему типа контейнера, такого как std :: string, он больше не будет знать или заботиться о том, как распределяется память, так как это все равно будет принадлежать звонящему. Это логическое завершение этой идеи: boost :: range , которая добавляет все перегруженные конструкторы, чтобы вызывающая сторона просто передавала строку / вектор / список / любой вид контейнера с помощью .begin () и. end () или отдельные итераторы.
Написав свой код обработки для работы с произвольным диапазоном итераторов, вы могли бы даже написать собственный итератор (не такой сложный, как кажется, просто объект с некоторыми стандартными определениями типов и оператором ++ / * / = / == /! = перегружен, чтобы получить итератор только для пересылки), который заботится о переходе к следующему фрагменту каждый раз, когда он попадает в конец того фрагмента, над которым он работает, пропуская пропуски (я полагаю, это то, что вы имели в виду под trim). То, что вам никогда не приходилось собирать всю цепочку подряд. Будет ли это победой, зависит от того, сколько фрагментов / сколько у вас фрагментов. По сути, это то, о чем говорил Мартин Йорк по веревке SGI: строка, в которой append образует связанный список фрагментов, а не непрерывный буфер, который, таким образом, подходит для гораздо более длинных значений.
ОБНОВЛЕНИЕ (поскольку я все еще вижу случайные отзывы об этом ответе):
C ++ 17 вводит другой выбор: std :: string_view , который заменил std :: string во многих сигнатурах функций, является несобственной ссылкой на символьные данные. Он неявно конвертируется из std :: string, но также может быть явно создан из смежных данных, принадлежащих где-то еще, избегая ненужного копирования, налагаемого std :: string.