我正在阅读"C++ Cookbook",其中有以下片段:
// cout << s << std::endl; // You shouldn't be able to
wcout << ws << std::endl; // run these at the same time
如果你有兴趣看实际的例子,这里有一个链接到谷歌图书的页面。
还有,我发现了这个SO question,它似乎声明混合wcout和cout是可以的。有人能给我解释一下这个评论在说什么吗?
- 编辑**
来自C标准[27.4.1]:
对相应的宽字符流和窄字符流的混合操作遵循与对FILE的混合操作相同的语义,如ISO C标准的修订1中所指定的。
来自C标准[7.19.2]:
每个流都有一个方向。在流与外部文件关联之后,但在对其执行任何操作之前,该流没有方向。一旦宽字符输入/输出函数应用于没有方向的流,该流就成为宽方向的流。类似地,一旦字节输入/输出函数应用于没有方向的流,流将成为面向字节的流。只有调用freopen函数或fwide函数才能改变流的方向。(成功调用freopen会删除任何方向。)
字节输入/输出函数不得应用于宽方向流,宽字符输入/输出函数不得应用于字节方向流。
所以,标准似乎说你不应该把它们混在一起。然而,我发现了这句话from this article:
对于Visual C10.0,fwide函数被记录为未实现。从实际的Angular 来看,至少在输出整行的级别上,混合使用cout和wcout显然工作得很好。因此,令人高兴的是,Visual C++显然忽略了标准的要求,没有维护不切实际的显式C FILE流方向。
另外,关于gcc,我发现了here中的这段话:
这是一个(新)特性,而不是bug,请参阅libstdc ++/11705和C标准(C99,7.19.2)中有关流定向的一般搜索。简单地说,您不能混合使用面向字节和面向宽的I/O。目前,由于libstdc ++/11705中指出的 * bug *,您可以通过调用std::ios::sync_with_stdio(false);在你节目的开头。
6条答案
按热度按时间ogsagwnx1#
当
cout
或wcout
第一次被调用时,stdout
的方向被设置。在cout
的情况下,stdout
成为一个字节方向的流,在wcout
的情况下,stdout
成为一个宽方向的流。根据C++标准[27.4.1]和C标准[7.19.2],一旦设置了流的方向,就不应该调用与该流的方向不兼容的函数。1zmg4dgp2#
违反标准中的“不应该“通常会让你陷入未定义行为的领域。未定义行为在某些实现中可能会很好地工作。
wqnecbli3#
从技术上讲,你完全可以同时使用窄流和宽流。然而,除非你安排它们对字符进行相同的编码,否则结果可能会很混乱。不幸的是,这伴随着一个警告,你不能控制标准流对象使用的编码,至少不能移植。即使编码是相同的,你需要确保部分字符被完全写入,也就是说,当切换到另一个宽度时,至少你需要刷新缓冲区。
5us2dqdw4#
我不知道。
除了线程,你不能"同时"运行两条语句。当然,你可以在程序的不同点使用
cout
和wcout
。它们都Map到STDOUT
,就这样......尽管在某些情况下,你可能会遇到不同的缓冲区,得到稍微出乎意料的顺序。显然,每一个都在"目的地"流
STDOUT
上注入了一个 * 方向 *,并且不允许在已经注入了方向[C++11: 27.4.1]
和[C99: 7.19.2]
的流上混合操作。yrwegjxp5#
我猜:
cout
和wcout
是两个不同的流,您提供的引号没有说明流方向与底层文件方向的相关性,可能流在幕后悄悄地重新调整stdout
的方向吗?czq61nw16#
std::ios::sync_with_stdio(false);
尝试此代码
我在
Debian10+GCC8.3.0
中执行它,结果是: