<cstdio> vs <iostream>

https://loremipsum.io

<cstdio> vs <iostream>


前言

讲道理我不希望越来越多的人知道stackoverflow,因为我已经预见到,如果放任现在的情况继续发展,现在的stackoverflow就是N年前的CSDN、博客园、知乎……
当然我也许不用如此悲观,因为他们天生不喜欢英文,哪怕那篇网页的内容就是眼下最急需的解决办法。一看到英文他们条件反射般的动作不外乎两种,一是关掉页面继续在中文内容的垃圾堆里乱翻乱找,二是打开手机上的翻译软件。(他们大概不知道DeepL的存在)
现在我最担心的是,国内不知道哪里冒出来的一类特定类型的内容农场,对于stackoverflow上的问题进行机翻“洗稿”以后当成自己的网站内容,堂而皇之地公开出来。

𝓈𝓫同事,𝓈𝓫领导,𝓈𝓫公司,我自己也是𝓈𝓫,要不然怎么会跟这一群𝓈𝓫匹配到一个区。
以下内容由本人纯手工翻译自这里,目的是作为自己的阅读笔记,本人不承担任何相关责任。


1

我最近才知道有ios_base::sync_with_stdio这么一个函数,让你可以关闭C++中iostream流与标准C中cstdio流之间的同步(如果你已经关闭了也可以用它打开)。

现在,我原以为C语言的stdout, stderrstdin在C++中本质上就是被封装在iostreams类的一组对象里而已,但是如果它们必须相互同步,就表明后者不是前者的包装器。

我对此缓缓打出一个问号?谁能澄清一下,C++的iostream和C的stdio是不同的东西,它们能做到完全相同的事情,只是在不同的抽象层次上?我以为它们是同一种东西!?

它们为什么必须同步?我一直以为它们本质上是同一个东西,只不过一个是另一个的包装器。

1

C 和 C++ 标准对功能的实现方式没有要求,只是对某些操作的效果做出了要求。就<stdio><iostream>的功能对比而言,这意味着其中一个可以是另一个的包装器,两者本质上是相同的,或者它们可以是相互独立而完全不同的。技术上讲,出于多种原因使用一种通用的实现会比较理想(例如不需要显式同步,或者存在一种确定的机制为用户定义系统扩展FILE*),但我不知道有哪个系统真的是这么做的。
让一种实现成为另一种的包装器是完全可能的,根据<stdio>去实现<iostream>也是一种典型的选择,尽管在某些操作上会引入额外开销是一个缺点,而且大多数C++标准库已经转而使用完全独立的实现。

不幸的是,不论是包装器的实现形式还是完全独立的实现形式,都面临一个共同的问题:在字符级别完成 I/O 的效率非常低。因此,基本上必须对字符进行缓冲,并从缓冲区读取或写入。这对于彼此独立的流非常有效。
但是有一个陷阱,对于标准C流stdin, stdout, stderr和它们在C++里各自的对等物(窄字符std::cin, std::cout, std::cerr/std::clog,宽字符std::wcin, std::wcout, std::wcerr/std::wclog):当用户同时从 stdinstd::cin 读取时会发生什么?如果这两个流中的任何一个从底层 OS 流中读取字符缓冲区,则读取将出现乱序。类似地,如果stdoutstd::cout使用互相独立的缓冲区,当用户同时向两者写入时,字符将以不可预料的顺序出现。因此,标准 C++流对象(std::cin, std::cout, std::cerr, std::clog 及其宽字符版本)有一些特殊规则,强制它们与<stdio>中各自的对等物进行同步。事实上,这意味着这些 C++ 对象要么直接使用通用实现,要么根据 <stdio> 实现并且不缓冲任何字符。

人们意识到,如果实现不共享同一个基础,那么这种同步的成本是相当可观的,并且对于某些用户来说可能是不必要的:如果一个用户仅使用<iostream>,其不会为额外的间接性买账,更重要的是,不用缓冲区而引入的额外开销,没人会买账。对于谨慎的实现来说,不使用缓冲区的代价可能是相当大的,因为这意味着某些操作最终不得不在每个迭代中进行检查(并可能进行虚函数调用),而不偶尔才进行一次。因此,std::sync_with_stdio() 可用于关闭这种同步,这可能意味着标准流对象在一定程度上完全改变了它们的内部实现。由于标准流对象的流缓冲区可以被用户替换,所以不幸的是,不能直接改变流缓冲区,但可以改变流缓冲区的内部实现。

<iostream> 库的良好实现中,所有这些只会影响标准流对象,即文件流完全不受影响。但是,如果你想使用标准流对象并希望获得良好的性能, 那就绝对不要混用<stdio><iostream> 并且注意关闭同步。尤其是在比较<stdio><iostream>的IO性能时,应该意识到这一点。

2

实际上 stdoutstderrstdin 是操作系统的文件处理程序。 C 的 FILE 结构以及 C++ 的 iostream 类都是这些文件处理程序的包装器。 iostream 类和 FILE 结构都可能有自己的缓冲区或其他需要同步的东西,以确保文件的输入或文件的输出正确完成。


TLDR

不要混用<stdio><iostream>


  1. https://stackoverflow.com/questions/9653751/cstdio-streams-vs-iostream-streams ↩︎

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值