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
?如果这些流中的任何一个从底层 OS 流中读取字符缓冲区,则读取将出现乱序。同样,如果两者stdout
和std::cout
当用户同时写入两个流时,使用的独立缓冲区字符将以意外的顺序出现。因此,标准 C++ 流对象(即std::cin
、std::cout
、std::cerr
和std::clog
它们的宽字符对应物)有一些特殊规则,要求它们与各自的<stdio>
对应物同步。实际上,这意味着这些 C++ 对象要么直接使用通用实现,要么根据<stdio>
不缓冲任何字符来实现。
人们意识到,如果实现不共享一个共同的基础,这种同步的成本是相当可观的,并且对于某些用户来说可能是不必要的:如果用户只使用<iostream>
他不想为额外的间接付费,更重要的是,他不想支付不使用缓冲区所带来的额外成本。对于谨慎的实现,不使用缓冲区的成本可能相当高,因为这意味着某些操作最终必须在每次迭代中进行检查,并且可能需要进行虚函数调用,而不是偶尔进行一次。因此,std::sync_with_stdio()
可用于关闭此同步,这可能意味着标准流对象或多或少完全改变了它们的内部实现。由于标准流对象的流缓冲区可以由用户替换,不幸的是,流缓冲区不能被替换,但流缓冲区的内部实现可以改变。
在<iostream>
库的良好实现中,所有这些仅影响标准流对象。也就是说,文件流应该完全不受此影响。但是,如果您想使用标准流对象并希望获得良好的性能,您显然不想混合<stdio>
并且<iostream>
想要关闭同步。特别是在比较 和 之间的 I/O 性能时<stdio>
,<iostream>
您应该意识到这一点。