提问人:Head Geek 提问时间:10/18/2008 最后编辑:General GrievanceHead Geek 更新时间:6/29/2023 访问量:264393
“std::endl” 与 “\n”
"std::endl" vs "\n"
问:
许多 C++ 书籍都包含这样的示例代码...
std::cout << "Test line" << std::endl;
...所以我也一直这样做。但是我看到了很多来自工作开发人员的代码,而不是这样的:
std::cout << "Test line\n";
是否有技术原因偏爱其中一种,或者只是编码风格的问题?
答:
可能存在性能问题,强制刷新输出流。std::endl
评论
它们都将写入适当的行尾字符。除此之外,endl 将导致缓冲区被提交。在执行文件 I/O 时,您通常不希望使用 endl,因为不必要的提交可能会影响性能。
假设文件在文本模式下打开,不同的行尾字符无关紧要,除非您要求二进制,否则您将得到该模式。编译后的程序将为编译的系统写出正确的东西。
唯一的区别是 std::endl
刷新输出缓冲区,而不是刷新输出缓冲区。如果不希望频繁刷新缓冲区,请使用 .如果这样做(例如,如果要获取所有输出,并且程序不稳定),请使用 .'\n'
'\n'
std::endl
评论
::std::cerr
::std::cout
stderr
./prog > file
差异可以通过以下几点来说明:
std::cout << std::endl;
相当于
std::cout << '\n' << std::flush;
所以
- 使用:如果要强制立即刷新输出。
std::endl
- 如果您担心性能,请使用(如果您使用运算符,则情况可能并非如此)。
\n
<<
我在大多数线路上使用。
然后在段落末尾使用(但这只是一种习惯,通常不是必需的)。\n
std::endl
与其他声明相反,仅当流要进入文件(并且是特殊但仍然是文件(或类似文件))时,字符才会映射到行序列的正确平台末尾。\n
std::cin
std::cout
评论
cout
cin
cin
cout
cin
operator<<
sync_with_stdio(false)
没什么大不了的,但 endl 在 boost::lambda 中不起作用。
(cout<<_1<<endl)(3); //error
(cout<<_1<<"\n")(3); //OK , prints 3
如果你要使用std::endl
a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;
a) 呼叫操作员一次。
b) 呼叫接线员两次。<<
<<
评论
std::cout << "Hello" << "\n";
<<
<<
\n
endl
如果你使用 Qt 和 ,你可能会不小心使用不正确的结果,这给你带来了非常令人惊讶的结果。请参阅以下代码片段:endl
endl
#include <iostream>
#include <QtCore/QtCore>
#include <QtGui/QtGui>
// notice that there is no "using namespace std;"
int main(int argc, char** argv)
{
QApplication qapp(argc,argv);
QMainWindow mw;
mw.show();
std::cout << "Finished Execution!" << endl;
// This prints something similar to: "Finished Execution!67006AB4"
return qapp.exec();
}
请注意,我写了而不是(这本来是正确的),显然在 qtextstream.h 中定义了一个函数(它是 QtCore 的一部分)。endl
std::endl
endl
使用而不是完全回避任何潜在的命名空间问题。
这也是一个很好的例子,为什么将符号放入全局命名空间(就像Qt默认所做的那样)是一个坏主意。"\n"
endl
评论
using namespace std;
我记得在标准中读到过这个,所以这里是:
请参阅 C11 标准,该标准定义了标准流的行为方式,因为 C++ 程序与 CRT 连接,因此 C11 标准应在此处管理刷新策略。
ISO/IEC 9899:201x 认证
7.21.3 第 7 节
在程序启动时,三个文本流是预定义的,不需要显式打开 — 标准输入(用于读取常规输入),标准输出(用于写入 常规输出)和标准误差(用于写入诊断输出)。与最初一样 打开时,标准误差流未完全缓冲;标准输入和标准 当且仅当可以确定流不引用时,输出流才会完全缓冲 到交互式设备。
7.21.3 第 3 节
当流未缓冲时,字符应从源或 尽快到达目的地。否则,字符可能会累积,并且 作为块传输到主机环境或从主机环境传输。当流完全缓冲时, 字符旨在作为块传输到主机环境或从主机环境传输,当出现以下情况时 缓冲区已填充。当流被行缓冲时,字符应为 当换行符 遇到。此外,字符旨在作为块传输到主机 环境,当缓冲区被填满时,当在无缓冲的流上请求输入时,或者 当在需要传输的线路缓冲流上请求输入时 主机环境中的字符。对这些特征的支持是 实现定义,并且可能受 setbuf 和 setVBUF 函数的影响。
这意味着当且仅当它们引用非交互式设备时,它们才被完全缓冲。换句话说,如果 stdout 附加到终端,则行为没有区别。std::cout
std::cin
但是,如果被调用,则即使对交互式设备也不会造成刷新。否则等同于除非通过管道连接到文件:std::endl 上的 c++ ref。std::cout.sync_with_stdio(false)
'\n'
'\n'
std::endl
参考:这是一个仅输出的 I/O 操纵器。
std::endl
在输出序列 os 中插入换行符,并像调用后跟 .os.put(os.widen('\n'))
os.flush()
何时使用:
该机械手可用于立即产生一行输出,
例如
显示长时间运行的进程的输出时,记录多个线程的活动或记录可能意外崩溃的程序的活动。
也
如果生成的进程执行任何屏幕 I/O,则在调用 std::system 之前,还需要显式刷新 std::cout。在大多数其他常见的交互式 I/O 方案中,std::endl 与 std::cout 一起使用时是多余的,因为来自 std::cin 的任何输入、到 std::cerr 的输出或程序终止都会强制调用 std::cout.flush()。在某些来源的鼓励下,使用 std::endl 代替 '\n' 可能会显著降低输出性能。
我从未见过有人说过受 cout 格式的影响:'\n'
#include <iostream>
#include <iomanip>
int main() {
std::cout << "\\n:\n" << std::setw(2) << std::setfill('0') << '\n';
std::cout << "std::endl:\n" << std::setw(2) << std::setfill('0') << std::endl;
}
输出:
\n:
0
std::endl:
请注意,由于是一个字符,填充宽度设置为 2,因此之前只打印了 1 个零。'\n'
'\n'
我在任何地方都找不到关于它的任何信息,但它使用 clang、gcc 和 msvc 重现。
当我第一次看到它时,我非常困惑。
评论
cout
ofstream
ofstream
endl
\n
xxd
endl
来自 GCC 文档:
有些人还认为,将 endl 发送到输出流只会写一个换行符。这是不正确的;写入换行符后,缓冲区也会被刷新。也许这就是你在写到屏幕时想要的效果 - 尽快把文本拿出来,等等 -- 但是当对文件这样做时,缓冲在很大程度上被浪费了:
output << "a line of text" << endl;
output << some_data_variable << endl;
output << "another line of text" << endl;
在这种情况下,正确的做法是将数据写出,让库和系统担心缓冲。如果你需要换行符,只需写一个换行符:
output << "a line of text\n"
<< some_data_variable << '\n'
<< "another line of text\n";
您可以检查ostream的文档,或检查实现本身 - 在我的案例中,usr/include/c++/11/ostream:684 -。在那里你会发现:endl
// Standard basic_ostream manipulators
/**
* @brief Write a newline and flush the stream.
*
* This manipulator is often mistakenly used when a simple newline is
* desired, leading to poor buffering performance. See
* https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering
* for more on this subject.
*/
template<typename _CharT, typename _Traits>
inline basic_ostream<_CharT, _Traits>&
endl(basic_ostream<_CharT, _Traits>& __os)
{ return flush(__os.put(__os.widen('\n'))); }
评论
'\n'
endl
endl