C ++:“std :: endl”vs“\ n”

时间:2008-10-17 21:25:17

标签: c++ coding-style iostream c++-faq

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

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

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

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

是否有技术上的理由偏爱另一个,或者仅仅是编码风格的问题?

14 个答案:

答案 0 :(得分:422)

变化的行尾字符无关紧要,假设文件在文本模式下打开,除非你要求二进制文件,否则这就是你得到的。编译后的程序将为编译的系统写出正确的内容。

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

答案 1 :(得分:214)

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

std::cout << std::endl;

相当于

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

所以,

  • 使用std::endl如果要强制立即刷新输出。
  • 如果您担心性能,请使用\n(如果您使用的是<<运营商,情况可能并非如此)。

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

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

答案 2 :(得分:40)

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

答案 3 :(得分:26)

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

参见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++ ref on std::endl

答案 4 :(得分:23)

如果您要使用std::endl

,那里会隐含另一个函数调用
a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;

a)调用运算符<<一次。
b)两次调用operator <<

答案 5 :(得分:18)

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

答案 6 :(得分:11)

不是什么大问题,但是endl won't work中的boost::lambda

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

(cout<<_1<<"\n")(3); //OK , prints 3

答案 7 :(得分:9)

如果你使用Qt和endl,你可能会意外地使用错误的endl,今天发生在我身上,我就像..WTF ??

#include <iostream>
#include <QtCore/QtCore> 
#include <QtGui/QtGui>
//notice that i dont have a "using namespace std;"
int main(int argc, char** argv)
{
    QApplication qapp(argc,argv);
    QMainWindow mw;
    mw.show();
    std::cout << "Finished Execution !" << endl << "...";
    // Line above printed: "Finished Execution !67006AB4..."
    return qapp.exec();
}

当然这是我的错误,因为我应该写std::endl但如果你使用endl,qt和using namespace std;它取决于包含文件的顺序如果使用正确的endl *

当然你可以重新编译Qt以使用命名空间,所以你得到上面例子的编译错误。

编辑:忘记提及,Qt的endl在“qtextstream.h”中声明,这是QtCore的一部分

* EDIT2:如果您有endl using或名称空间std::cout,C ++会选择正确的std,因为std::endl是相同的命名空间为std::cout,C ++的ADL机制将选择std::endl

答案 8 :(得分:2)

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

答案 9 :(得分:1)

我从未见过有人说过 '\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 个零。

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

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

答案 10 :(得分:0)

使用reference这是仅输出I / O操纵器

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

何时使用:

此操纵器可用于立即生成一行输出

例如

  

显示长时间运行的进程的输出时,记录多个线程的活动或记录可能意外崩溃的程序的活动。

同时

  

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

答案 11 :(得分:0)

如果打算在自己的笔记本电脑以外的其他任何设备上运行程序,则永远不要使用endl语句。尤其是如果您要写很多短行或者我经常在文件中看到单个字符。众所周知,使用endl可以杀死网络文件系统,例如NFS。

答案 12 :(得分:0)

endl操纵器等效于'\'。但是endl总是刷新流。

std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush

答案 13 :(得分:-22)

如果您没有注意到,endl就像按下ENTER键,"\n"就像按ENTER键+空格键一样。