Стандарты C и C ++ не предъявляют требований к тому, как все реализовано, а только к тому, каков эффект определенных операций.Для функциональности <stdio>
против <iostream>
это означает, что один может обернуть другой, оба могут быть по существу одинаковыми или что они либо полностью независимы.Технически, использование общей реализации было бы идеальным по нескольким причинам (например, не было бы необходимости в явной синхронизации и был бы определенный механизм для расширения FILE*
для пользовательских систем), но я не знаю ни одной системы, которая на самом делеЯвляется ли это.Возможно иметь одну реализацию как оболочку другой, и реализация <iostream>
s в терминах <stdio>
была типичным выбором реализации, хотя у нее есть недостаток, заключающийся в том, что она требует дополнительных затрат для определенных операций, и большинство стандартных библиотек C ++ перешли наиспользовать полностью отдельные реализации.
К сожалению, как у обернутой, так и у независимой реализации есть общая проблема: ввод / вывод ужасно неэффективен, когда выполняется один символьный уровень.Таким образом, по существу, необходимо буферизовать символы и выполнять чтение или запись в буфер.Это хорошо работает для потоков, которые не зависят друг от друга.Подвох - это стандартные C-потоки stdin
, stdout
, stderr
и их узкие символы C ++ std::cin
, std::cout
, std::cerr
/ std::clog
и аналоги широких символов C ++ std::wcin
, std::wcout
, std::wcerr
/ std::wclog
соответственно: что происходит, когда пользователь читает как из stdin
, так и std::cin
?Если какой-либо из этих потоков читает буфер символов из базового потока ОС, чтения будут отображаться не по порядку.Точно так же, если бы оба stdout
и std::cout
использовали независимые буферы, символы появлялись бы в неожиданном порядке, когда пользователь записывает оба потока.В результате существуют специальные правила для стандартных потоковых объектов C ++ (т. Е. std::cin
, std::cout
, std::cerr
и std::clog
и их аналоги с широкими символами), которые предписывают синхронизировать их с соответствующими аналогами <stdio>
,По сути, это означает, что конкретно эти объекты C ++ либо напрямую используют общую реализацию, либо они реализованы в терминах <stdio>
и без буферизации каких-либо символов.
Было понято, чтостоимость такой синхронизации весьма существенна, если реализации не разделяют общую базу и могут быть ненужными для некоторых пользователей: если пользователь использует только <iostream>
, он не хочет платить за дополнительное косвенное обращение и, что более важно,он не хочет платить за дополнительные расходы, связанные с отсутствием буфера.Для осторожных реализаций стоимость неиспользования буфера может быть весьма существенной, потому что это означает, что определенные операции в конечном итоге должны выполнять проверку и, возможно, вызов виртуальной функции в каждой итерации, а не только время от времени.Таким образом, std::sync_with_stdio()
может использоваться для отключения этой синхронизации, что может означать, что стандартные объекты потока более или менее полностью изменяют свою внутреннюю реализацию.Поскольку потоковые буферы стандартных потоковых объектов могут быть заменены пользователем, к сожалению, потоковые буферы не могут быть заменены, но внутренняя реализация потокового буфера может быть изменена.
В хороших реализациях *Библиотека 1037 * все это влияет только на стандартные объекты потока.То есть файловые потоки не должны быть полностью затронуты этим.Однако если вы хотите использовать стандартные потоковые объекты и хотите добиться хорошей производительности, вы явно не хотите смешивать <stdio>
и <iostream>
и хотите отключить синхронизацию.Особенно при сравнении производительности ввода / вывода между <stdio>
и <iostream>
вы должны знать об этом.