635

许多 C++ 书籍都包含这样的示例代码......

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

...所以我也一直这样做。但是我已经看到很多这样的工作开发人员的代码:

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

是否有技术上的理由比另一个更喜欢一个,或者这只是编码风格的问题?

4

13 回答 13

528

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

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

于 2008-10-17T21:56:50.490 回答
280

可以通过以下方式说明差异:

std::cout << std::endl;

相当于

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

所以,

  • 如果std::endl要强制立即刷新到输出,请使用。
  • 如果\n您担心性能(如果您使用<<运算符,则可能不是这种情况),请使用。

\n在大多数线路上使用。
然后std::endl在段落末尾使用(但这只是一种习惯,通常不需要)。

与其他声明相反,\n仅当流将转到文件(std::cin并且std::cout是特殊但仍然是文件(或类似文件))时,字符才会映射到正确的平台行尾序列。

于 2008-10-17T22:43:44.513 回答
45

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

于 2008-10-17T21:28:21.297 回答
32

如果您要使用,那里隐含另一个函数调用std::endl

a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;

a) 呼叫操作员<<一次。
b) 呼叫接线员<<两次。

于 2009-11-17T22:29:29.693 回答
32

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

请参阅 C11 标准,该标准定义了标准流的行为方式,因为 C++ 程序与 CRT 接口,C11 标准应在此处管理刷新策略。

ISO/IEC 9899:201x

7.21.3 §7

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

7.21.3 §3

当流未缓冲时,字符应尽快从源或目标出现。否则,字符可能会作为一个块累积并传输到主机环境或从主机环境传输。当一个流被完全缓冲时,当缓冲区被填满时,字符将作为一个块传输到主机环境或从主机环境传输。当流被行缓冲时,当遇到换行符时,字符将作为块传输到主机环境或从主机环境传输。此外,当缓冲区被填满时,当在非缓冲流上请求输入时,或者当在需要从主机环境传输字符的行缓冲流上请求输入时,字符将作为块传输到主机环境.

这意味着当std::cout仅当它们引用非交互式设备时,它们才会std::cin被完全缓冲。换句话说,如果标准输出连接到终端,那么行为没有区别。

但是,如果std::cout.sync_with_stdio(false)被调用,则'\n'即使对交互式设备也不会造成刷新。否则'\n'等效于std::endl除非管道到文件:c++ ref on std::endl

于 2014-08-29T13:58:14.080 回答
20

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

于 2008-10-17T21:33:32.207 回答
12

没什么大不了的,但是endl在boost::lambda中不起作用

(cout<<_1<<endl)(3); //error

(cout<<_1<<"\n")(3); //OK , prints 3
于 2009-02-22T01:57:21.803 回答
12

如果您使用 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.hendl中定义了一个函数(它是 QtCore 的一部分)。

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

于 2010-02-17T01:21:12.987 回答
5

机械手std::endl相当于 。'\n'std::endl总是刷新流。

std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush
于 2019-05-24T11:12:32.720 回答
4

我从未见过有人说'\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,因此之前只打印了 1 个零'\n'

我在任何地方都找不到任何关于它的信息,但它可以用 clang、gcc 和 msvc 重现。

当我第一次看到它时,我非常困惑。

于 2021-08-07T12:47:42.093 回答
2

我一直有只使用 std::endl 的习惯,因为它很容易让我看到。

于 2008-10-17T21:53:29.717 回答
2

如果您打算在您自己的笔记本电脑以外的任何其他设备上运行您的程序,请永远不要使用该endl语句。特别是如果您要编写很多短行,或者我经常在文件中看到单个字符。使用endlis known to kill 像 NFS 这样的网络文件系统。

于 2018-10-27T23:32:02.223 回答
1

参考这是一个仅输出 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' 可能会显着降低输出性能。

于 2018-03-27T11:58:16.470 回答