Путаница потоков C++: итератор istreambuf против итератора istream?

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

2 ответов


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

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

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

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

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


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

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

enter image description here

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

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

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

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

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

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

enter image description here

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