Вопрос по c++ – Путаница в потоках C ++: istreambuf_iterator против istream_iterator?

40

В чем разница междуistreambuf_iterator а такжеistream_iterator? And in general what is the difference between streams and streambufs? I really can't find any clear explanation for this so decided to ask here.

смотрите такжеwhat-exactly-is-streambuf-how-do-i-use-it 陳 力

Ваш Ответ

2   ответа
42

вода. По сути, семейство streambuf выполняет всю работу, связанную с IO, а семейство IOstream используется только для форматирования и преобразования в строку / из строки.

В настоящее время,istream_iterator принимает аргумент шаблона, который говорит, что неотформатированная последовательность строк из streambuf должна быть отформатирована как, например,istream_iterator<int> будет интерпретировать (разделенный пробелами) весь входящий текст какint S.

С другой стороны,istreambuf_iterator заботится только о необработанных символах и выполняет итерации непосредственно над соответствующим потоковым буферомistream что это пройдет.

В общем, если вас интересуют только необработанные символы, используйтеistreambuf_iterator. Если вы заинтересованы в форматированном вводе, используйтеistream_iterator.

Все сказанное относится и кostream_iterator а такжеostreambuf_iterator.

"Обычно, если вас интересуют только необработанные символы, используйте istream_iterator" - это должно бытьistreambuf_iterator? Mankarse
@ Mankarse: Хм, конечно, спасибо. Xeo
Это сделало это намного понятнее для меня, спасибо! dextrey
Просто одна небольшая деталь: семейство iostream на самом деле тоже не выполняет большую часть форматирования - оно в основном делегировано языку, связанному с потоком. Iostream - это, по сути, «создатель матчей», объединяющий локаль с потоковым буфом. Хотя большая часть реальной работы делегирована одному или другому. Jerry Coffin
@ Xeo: Как бы я ни хотел, я точно не могу винить тебя за это! Jerry Coffin
11

как таково, практически не имеет ничего общего с чтением или записью из / в файл на вашем компьютере.

Iostream в основном выступает в роли «сваха» между streambuf и локалью:

В iostream хранится информация о том, как должны выполняться преобразования (например, текущая ширина и точность преобразования). Он использует их для указания локали, как и где выполнять преобразование (например, преобразовать это число в строку в этом буфере с шириной 8 и точностью 5).

Хотя вы и не спрашивали об этом напрямую, локаль, в свою очередь, на самом деле является просто контейнером, но (как ни странно) типичным безопасным гетерогенным контейнером. Вещи, которые он содержит, являютсяfacets. Объект фасета определяет один фасет общей локали. Стандарт определяет количество аспектов для всего, от чтения и записи чисел num_get, num_put) для классификации символов (фасет ctype).

По умолчанию поток будет использовать локаль "C". Это довольно просто - числа просто преобразуются в поток цифр, единственное, что он распознает как буквы, это 26 строчных букв и 26 заглавных английских букв и так далее. Вы можете, однако,imbue поток с другим языком по вашему выбору. Вы можете выбрать локали для использования по именам, указанным в строках. Особенно интересен тот, который выбран пустой строкой. Использование пустой строки в основном говорит библиотеке времени выполнения о выборе локали, которую она «считает» наиболее подходящей, обычно в зависимости от того, как пользователь сконфигурировал операционную систему. Это позволяет коду работать с данными в локализованном формате без явного написания для какой-либо конкретной локали.

Итак, основная разница междуistream_iterator иistreambuf_iterator заключается в том, что данные, поступающие из istreambuf_iterator, не прошли (большинство из) преобразований, выполняемых языковым стандартом, но данные, поступающие изistream_iterator был преобразован локалью.

Для чего стоит, что «большая часть» в предыдущем абзаце относится к тому факту, что когда вы читаете данные из istreambuf (через итератор или иным образом) одно небольшое преобразование на основе локалиявляетс done: наряду с различными видами «форматирования» локаль содержит фасет codecvt, который используется для преобразования внешнего представления в некоторое внутреннее представление (например, UTF-8 в UTF-32).

Возможно, имеет больше смысла игнорировать тот факт, что они оба хранятся в локали, и думать только об отдельных задействованных аспектах:

Так что это реальная разница междуistream_iterator иistreambuf_iterator. Небольшое преобразование (по крайней мере, потенциально) выполняется для данных любого из них, но по существуМеньш делается для данных, поступающих отistreambuf_iterator.

Хорошее объяснение. А как насчет непосредственного использования streambufs для необработанных двоичных данных? Pavel
@ Павел: Это не то, как работают iostreams в C ++, но, по крайней мере, теоретически, нет причин, по которым они не могли. Я сомневаюсь, что вы хотели бы, хотя - если бы вы сделали, вы должны применитьcodecvt преобразование по одному символу за раз, когда вы читаете данные из необработанного буфера, который, как я считаю, обычно теряет приличную скорость (по сравнению с преобразованием всего буфера за раз). Jerry Coffin
Вот почему я не хочу использовать iostreams, потому что я не хочу, чтобы этот кодекс включался. Pavel
@ Pavel: Вы все еще можете использовать iostreams - вам просто нужно написать свой собственный буфер потока, который обрабатывает переполнение (если это входной поток) и / или переполнение (если это выходной поток) и читает / записывает необработанные данные, без делает преобразование кода. Большинство написанных мной потоковых буферов не выполняют никакого преобразования кода. Jerry Coffin
@ Павел: Если вы не делаете что-то ужасно неправильное (например, используяstd::endl где тебе нужно было только\n) iostreams вполне конкурентоспособны с C I / O по скорости. Stackoverflow.com / а / 1926432/179910 Jerry Coffin

Похожие вопросы