Будируется ли std:: cout?

Просто прочитав старую, но интересную статью "Скотт Майерс"

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

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

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

  • std::cout не был буферизирован.
  • Состояние ios::unitbuf на std:: cout явно не определено (зависит от реализации).

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

Ответы

Ответ 1

Да, он забуферирован:

С++ 11 27.4.2 [узкие. потоки.объектов]/3: Объект cout управляет выводом в буфер потока, связанный с объектом stdout

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

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

Ответ 4

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

Итак, если вы перенаправляете вывод (используя " > " в ​​UNIX), то буферизованное поведение срабатывает.

Подробнее в связанном сообщении.

Ответ 5

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

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

//system crash!

cout << endl;