Подтвердить что ты не робот

Путаница потоков С++: istreambuf_iterator vs istream_iterator?

В чем разница между istreambuf_iterator и istream_iterator? И вообще в чем разница между потоками и streambufs? Я действительно не могу найти никаких ясных объяснений для этого, поэтому решил спросить здесь.

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

iostream в основном выступает как "сваха" между streambuf и locale:

введите описание изображения здесь

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

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

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

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

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

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

введите описание изображения здесь

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