Стандарты C и C++ не требуют каких-либо требований к тому, как реализованы вещи, как раз то, что влияет на определенные операции. Для функциональности <stdio>
vs. <iostream>
это означает, что можно обернуть другой, оба могут быть по существу одинаковыми или что они либо полностью независимы. Технически использование общей реализации было бы идеальным по нескольким причинам (например, не было бы необходимости в явной синхронизации, и был бы установлен механизм для расширения FILE*
для пользовательских систем), но я не знаю о какой-либо системе, которая на самом деле делает это , Возможна одна реализация - обертка другого, и реализация <iostream>
s в терминах <stdio>
была типичным вариантом реализации, хотя она имеет недостаток, что она вводит дополнительную стоимость для определенных операций, и большинство стандартных библиотек C++ перешли на использование полностью отдельных реализации.
К сожалению, как обернутая, так и независимая реализация имеют общую проблему: I/O является ужасно неэффективным, когда выполняется один уровень персонажа. Таким образом, по существу, необходимо буферизовать символы и читать или записывать в буфер. Это хорошо работает для потоков, которые независимы друг от друга.Загвоздка являются стандарт 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()
может использоваться для выключения этой синхронизации, что может означать, что стандартные потоковые объекты более или менее полностью изменяют свою внутреннюю реализацию. Поскольку потоковые буферы стандартных объектов потока могут быть заменены пользователем, к сожалению, буферы потока не могут быть заменены, но внутренняя реализация буфера потока может быть изменена.
В хороших реализациях библиотеки <iostream>
все это влияет только на стандартные объекты потока. То есть, файловые потоки должны быть полностью не затронуты этим. Однако, если вы хотите использовать стандартные объекты потока и хотите достичь хорошей производительности, вы явно не хотите смешивать <stdio>
и <iostream>
, и вы хотите отключить синхронизацию. В частности, при сравнении производительности ввода-вывода между <stdio>
и <iostream>
вы должны знать об этом.
+1, woah Я всегда думал, что C++ 'iostream' был оберткой C' stdio'. – ApprenticeHacker