缓冲区刷新:"\n"与std::endl的区别

13

可能重复:
C++:“std::endl” vs“\ n”

Accelerated C++ 中提到了两件事:

  1. 大多数系统花费大量时间将字符写入输出设备。因此,C ++ 积累要写入缓冲区的字符并等待刷新缓冲区。

  2. 一种缓冲区可以被刷新的方法是如果我们明确告诉它这样做,使用 std::endl

这让我想知道:显然,除了最大的输出之外,好处非常小且不可感知,但是使用 "\n" 比使用 std::endl 快,还是 "\n" 也会刷新缓冲区?


1
是的,这是一个实现细节,所以你不会得到一个确定的答案。我的猜测是,在大多数实现中,这会有所区别,但这并不一定是正确的。 - Niklas B.
@Carl -- 诚然,我没有这样做,我甚至不知道该怎么做。我正在阅读这本书,我很好奇,所以我想问一下。 - user1253795
2个回答

11

使用 '\n' 不会刷新缓冲区,实际上比使用 std::endl 更快。

在典型的 I/O 操作中,输出会被缓冲起来,然后再写入到目标设备。这样,在写入到访问速度较慢的设备(例如文件)时,就不必每个字符都访问一次该设备。刷新操作会将缓冲区“刷新”到设备中,从而导致明显的性能开销。

-摘自:C++ - endl and flushing the buffer


1
对于“更快”的一些[通常]非常小的值;-) - user166390
2
@pst:嗯,当将大量数据输出到文件时,实际上可能会影响性能(当我写入几十MB的CSV数据时,曾经发生过这种情况)。 - Matteo Italia
@MatteoItalia 确实,我没有考虑到反向情况 :( - user166390
@MatteoItalia:另一方面,iostream不是输出内容的最快方式,因此还有许多其他因素会对性能产生负面影响。 - SigTerm
3
@SigTerm:iostreams 的设计很糟糕,但在 g++ 实现中,我发现它在几个场合比 C 标准输入输出库略快。 - Matteo Italia

0

我想补充一下,我认为将'\n'写入流中的含义可能与在第三方库中写入std::endl/std::flush不同。

例如,在当前项目中,我正在使用基于ostream的记录器。该记录器使用std::stringstream功能进行输出格式化,但已覆盖了刷新操作符。这样可以在日志中写入'\n'而无需刷新,并简化代码。

以下是伪代码示例:

class MyStream
{
    // [cut]
    std::stringstream m_buffer;
    // [cut]
};

// friends:
template <typename Printable>
MyStream& operator<<(MyStream& stream, const Printable& value)
{
     stream.m_buffer << value;
}

typedef decltype(std::flush) TManipulator;
template <>
MyStream& operator<<(MyStream& stream, const TManipulator& manipulator)
{
     if ( manipulator == std::flush || manipulator == std::endl )
         stream.sendLogLine();
     else
         stream.m_buffer << manipulator;
}

// usage sample
void main()
{
    getLoggerStream() << "hello" << std::endl;
}

顺便说一句,我不喜欢子类化std::stringstream,所以MyStream是一个适配器。如果我想让'\n'刷新,我应该重新实现更多的功能,包括char*std::string和其他特殊化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接