“std:: endl"与“\ n"

许多c++书籍包含这样的示例代码…

std::cout << "Test line" << std::endl;

...所以我也一直这么做。但我看到过很多开发者写的这样的代码:

std::cout << "Test line\n";

是否有技术上的原因,更喜欢其中一个,或者只是编码风格的问题?

243197 次浏览

可能存在性能问题,std::endl强制刷新输出流。

它们都将写入适当的行尾字符。除此之外,endl将导致缓冲区被提交。在执行文件I/O时,通常不希望使用endl,因为不必要的提交会影响性能。

不同的行结束字符无关紧要,假设文件以文本模式打开,除非您要求二进制,否则您将得到文本模式。编译后的程序将为被编译的系统写出正确的东西。

唯一的区别是std::endl会刷新输出缓冲区,而'\n'不会。如果不希望频繁刷新缓冲区,请使用'\n'。如果这样做(例如,如果您想获得所有输出,而程序不稳定),请使用std::endl

这种差异可以用下面的例子来说明:

std::cout << std::endl;

等于

std::cout << '\n' << std::flush;

所以,

  • 如果您想强制立即刷新输出,请使用std::endl
  • 如果担心性能问题,请使用\n(如果使用<<操作符,情况可能就不是这样了)。

我使用\n在大多数行 然后在段落末尾使用std::endl(但这只是一个习惯,通常不是必要的)

与其他声明相反,\n字符仅当流要传输到文件(std::cinstd::cout是特殊的,但仍然是文件(或类文件)时才会映射到行序列的正确平台末端。

没什么大不了的,但Endl行不通boost::λ中。

(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)调用operator <<一次。< br > b)调用operator <<两次

如果您使用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();
}

注意,我写了endl而不是std::endl(这本来是正确的),显然在qtextstream.h中定义了endl函数(这是QtCore的一部分)。

使用"\n"而不是endl完全避免了任何潜在的名称空间问题。 这也是一个很好的例子,为什么把符号放在全局命名空间(就像Qt默认做的那样)是一个坏主意

我记得在标准中读到过这个,所以是这样的:

参见C11标准,它定义了标准流的行为,作为c++程序接口的CRT, C11标准应该管理这里的刷新策略。

ISO / IEC 9899:201x

7.21.3§7

在程序启动时,三个文本流是预定义的,不需要显式地打开 标准输入(用于读取常规输入),标准输出(用于写入 常规输出)和标准错误(用于写入诊断输出)。按照最初的 打开时,标准错误流没有完全缓冲;标准输入和标准 当且仅当可以确定输出流不被引用时,输出流将被完全缓冲

7.21.3§3

当流未缓冲时,字符将从源端或从源端出现 尽快到达目的地。否则字符可能会累积和 作为块传输到或从主机环境。当一个流被完全缓冲时, 字符将作为块传输到主机环境或从主机环境传输 缓冲区被填满。当一个流是行缓冲的时候,字符应该是行缓冲的 为换行符时,以块的形式传输到主机环境或从主机环境传输 遇到。此外,字符打算作为一个块传输到主机 当缓冲区被填充时,当在未缓冲的流上请求输入时,或者 在需要传输的行缓冲流上请求输入时 来自主机环境的字符。对这些特性的支持 实现定义的,可能会受到setbuf和setvbuf函数的影响

这意味着std::coutstd::cin是完全缓冲的当且仅当它们指的是一个非交互设备。换句话说,如果stdout附加到终端,那么行为上没有区别。

然而,如果std::cout.sync_with_stdio(false)被调用,那么'\n'即使对交互设备也不会导致刷新。否则,'\n'相当于std::endl,除非管道到文件:c++引用std::endl

这是一个仅输出I/O操纵器

std::endl在输出序列os中插入一个换行符,并像调用os.put(os.widen('\n'))os.flush()一样刷新它。

使用时间:

这个操纵符可以用来产生一行立即输出

# EYZ0

当显示来自长时间运行的进程、多个线程的日志活动或可能意外崩溃的程序的日志活动的输出时。

如果派生进程执行任何屏幕I/O,则在调用std::system之前还需要显式刷新std::cout。在大多数其他常见的交互式I/O场景中,std::endl与std::cout一起使用时是冗余的,因为std::cin的任何输入、std::cerr的输出或程序终止都会强制调用std::cout.flush()。使用std::endl来代替'\n',这被一些来源所鼓励,可能会显著降低输出性能。

我从未见过有人说'\n'会受到cout格式的影响:

#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:


注意,由于'\n'是一个字符,填充宽度设置为2,因此在'\n'之前只打印了1个0。

我在任何地方都找不到关于它的任何东西,但它会用clang, gcc和msvc复制。

我第一次看到它的时候非常困惑。