繁体   English   中英

“std::endl” 与 “\n”

[英]"std::endl" vs "\n"

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

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

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

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

是否有技术原因偏爱其中一个,或者仅仅是编码风格的问题?

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

唯一的区别是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是特殊的但仍然是文件(或类似文件)) .

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

如果您要使用std::endl ,则其中隐含了另一个函数调用

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

a) 调用 operator <<一次。
b) 调用 operator <<两次。

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

请参阅 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

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

没什么大不了的,但endlboost::lambda 中不起作用

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

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

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

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

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

std::endl操作std::endl等价于'\\n' 但是std::endl总是刷新流。

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

参考这是一个仅输出的 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 .冲洗()。 某些来源鼓励使用 std::endl 代替 '\\n' 可能会显着降低输出性能。

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

我从未见过有人说'\\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'是一个字符并且 fill 设置为 2,所以在'\\n'之前只打印了 1 个零。

我在任何地方都找不到关于它的任何信息,但它可以使用 clang、gcc 和 msvc 进行复制。

当我第一次看到它时,我超级困惑。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM