2014-11-17 8 views
16

Просто читать старую, но интересную статью «Скотт Мейерс»Является ли std :: cout буферизированным?

http://aristeia.com/Papers/C++ReportColumns/novdec95.pdf

В основном речь идет о предпочитая использовать '\n' над std::endl (я согласен с и использовал то же увеличивающее в течение многих лет).

НО последний раздел показывает, что это не был включен в его книгу, потому что все это было вынесено спорно из-за двух пунктов:

  1. std::cout не буферизацией.
  2. Состояние ios::unitbuf на std :: cout не определено явно (при этом зависит от реализации).

Я сделал быстрый взгляд, но не смог найти ясную ссылку на стандарты для 1. Является ли std::cout неподтвержденным вопреки тому, что я всегда понимал?

+0

У этого есть информация: http://stackoverflow.com/questions/11392511/c-buffered-stream-io – stijn

ответ

2

Из чего я читаю форму here, cout обычно буферизуется, но когда он обнаруживает, что он печатает в интерактивной среде, например, на консоли, он возвращается к небуферизованным.

Так что, если вы перенаправить вывод (с помощью «>» в ​​UNIX), то буферизованные пинки поведение в.

Более подробную информацию в связанном сообщении.

+0

Вы вводите в заблуждение 'stdout' и' std :: cout'. Первая строка буферизируется для терминалов и блочно-буферизованная в противном случае. –

+0

То, что я сказал, такое же, как у Джерри Коффина и как написано в стандарте C99. – Alexandru

+1

Я не думаю, что 'std :: cout' упоминается в стандарте C99. –

16

Да, это буферном:

C++ 11 27.4.2 [narrow.stream.objects]/3 : Объект cout управляет выходом в буфер потока, связанного с объектом stdout

Статья ссылается на проект 1995 года, который стал стандартом C++ 98. Я понятия не имею, могло ли это сказать что-то другое.

Что касается пункта 2, unitbuf изначально ложна на всех потоков (указанных пост-условий basic_ios конструктора), для cerr и wcerr, которые явно указано иное, за исключением. Опять же, это может быть различным в упоминании древнего проекта.

+0

Я видел это. Но если вы прочтете следующий параграф. Он говорит то же самое о std: cerr, который не буферизирован. Поэтому я не был уверен, что слово «буфер» здесь не перегружено. 'Объект cerr управляет выводом в буфер потока, связанный с объектом stderr' –

+2

@LokiAstari:' cerr' также буферизуется. Разница в том, что у него есть 'unitbuf', поэтому он автоматически покраснет после каждой строки. –

+0

ОК. В этом есть смысл. –

2

Согласно этой странице - http://www.programmingincpp.com/flush-the-output-stream-buffer.html - std :: cout буферизуется. Я что-то не печатать, потому что крах программы произошло после соиЬ < < ... заявление, но до его продувают:

cout << "My error or flag message, but it's not flushed, so I never see it"; 

//system crash! 

cout << endl; 
9

Стандарт C++ определяет весь ввод и вывод как «как будто» все чтения и запись в конечном счете, произошло с помощью операции чтения и записи потоков C ([iostream.objects.overview]):

заголовок объявляет объекты, которые связывают объекты со стандартными потоками C, предусмотренных функций, объявленных в (27.9.2) и включает все заголовки, необходимые для использования этих объектов.

Для поведения стандартных потоков C, прикрепленных к этим объектам, мы должны обратиться к стандарту C (§7.19.3):

При запуске программы, три текстовых потоки предопределены и не нужно открывать явно - стандартный ввод (для чтения обычного ввода), стандартный выход (для записи обычного выхода) и стандартная ошибка (для записи диагностического вывода). По мере открытия стандартный поток ошибок не полностью буферизуется; стандартные входные и стандартные потоки вывода полностью буферизуются тогда и только тогда, когда можно определить поток, чтобы не ссылаться на на интерактивное устройство.

Здесь я цитирую стандарт C99, но я уверен, что (по модулю изменения нумерации разделов) то же самое во всех версиях стандарта C.

+0

Из памяти это не изменилось с C90 и соответствует требованиям в оригинальных руководствах Unix для C. С другой стороны, он спрашивал о C++, а C++ имеет разные правила. (В частности, C++ не имеет понятия буферизации строк.) –

10

Во-первых, нет требования, чтобы std::cout (или даже std::cerr) be небуферизованный. Единственным требованием является то, что std::cerr имеют std::basic_ios::unitbuf набор (так, что он будет заподлицо в конце каждого выходная функция: << или неформатная выходная функция). С другой стороны, если вы не вызвали std::basic_ios::sync_with_stdio(false), , вывод в потоки C++ и вывод в соответствующие потоки C (т. Е. std::cout и stdout) должны иметь одинаковые эффекты. В теории, это может быть сделано несколько способов: stdout функций могут вперед те std::cout, std::cout выхода может направить stdout, или они могут совместно использовать некоторые общие реализации буфера под капота. На практике практически все реализации имеют std::cout пересылка на stdout.

С определяет, что stderr не может быть полностью буферизация, и что stdout может быть полностью буферном только тогда, когда она может быть определена не для обозначения интерактивного устройства (для некоторой реализации определенного значения «интерактивного устройства»). Как правило, stdout будет линия буферизацией (а понятие, которое не существует в iostream), и stderr будет небуферизован, но это не гарантируется стандартом C (и не может быть правда сегодня — последний раз, когда я действительно смотрел было более двадцати лет назад). Во всяком случае, реализация которых только направляет stdout будет следовать правилам реализации C она направляет, и один, что оленья кожа»все еще необходимо предпринять некоторые шаги, чтобы гарантировать, что выход на std::cout и stdout выходит в правильном порядке, и что stdout ведет себя «как если бы», он подчинялся правилам C.

Если вы беспокоитесь о производительности, вы можете захотеть запустить некоторые тесты . Попробуйте измерение времени, которое требуется для вывода на std::ofstream вы открыли себя, по сравнению с временем, которое требуется для вывода std::cout (оба с и без заехав sync_with_stdio), с выходом перенаправлен. Различия должны быть интересными.

Смежные вопросы