告诉"endl"不要刷新

Tell `endl` not to flush

本文关键字:quot 刷新 endl 告诉      更新时间:2023-10-16

我的程序将大量短行打印到cout

作为一个略显做作的例子,我的行看起来有点像:

cout<<"The variable's value is: "<<variable<<endl;

我希望程序能快速运行,而且我确实相信endl正在杀死我,因为每次使用它时,它都会在cout上启动缓冲区刷新。

现在,互联网上的一些人说我可以这样做:

cout<<"The variable's value is: "<<variable<<"n";

但这似乎不是一个好的解决方案,因为endl抽象了可能指定终点线的特定系统特定方式,而n没有。这似乎也是一个糟糕的解决方案,因为如果我将来需要缓冲,我将不得不修改整个代码库。

因此,我想问,有没有办法禁用endl的缓冲区刷新方面?

编辑

进一步挖掘似乎表明endln都尊重操作系统可能选择的结束其行的各种方式。输出流似乎还检测到它是否处于潜在的交互状态,并相应地进行缓冲和刷新。因此:这个问题可以通过手动告诉输出流执行主动缓冲来解决。。。如果我能想办法的话。

endl抽象了特定于系统的方式,可以指定结束行,其中as \n没有"。

std::endl被定义为输出'n',然后进行刷新。系统特定的换行符的正确抽象就是'n'

为了防止刷新,不使用std::endl。此外,如果标准输出连接到或可能连接到交互式设备,则可以对其进行行缓冲,在这种情况下,换行符将刷新流。如果有问题,请使用连接到命名文件的ofstream。我认为在类Unix系统上,只有当标准输出是终端时,才会发生行缓冲。

endl刷新。如果你不想要这种行为,就不要使用endl。如果你想轻松地更改代码,可以使用自己的操纵器:

inline std::ostream& myendl( std::ostream& os ){
os.put(os.widen('n'));
return os;
}

这样,您就可以在一个地方轻松地更改myendl的行为。

根据http://en.cppreference.com/w/cpp/io/manip/endl

endl::在输出序列os中插入一个换行符,并通过调用os.put(os.widen('n'))os.flush()对其进行刷新。

因此,您似乎只想编写os.put(os.widen('n')),从这个定义来看,它应该是安全、可移植和正确的,并满足您的主要需求。

有一个std::nounitbuf,它被证明在这件事上有一些影响。然而,我没有注意到任何区别。为了绕过ostream关于何时或何时不冲洗的所有想法,我尝试了这个:

std::ostringstream oss;
//  std::cout << std::nounitbuf;
for( int i = 0; i < 1000000; i++ ){
//  std::cout <<  "Test " << "file" << 'n';
oss <<  "Test " << "file" << 'n';
}
std::cout << oss.str();

这将执行时间从约33秒提高到约25秒。

如果你的输出到xterm,你的执行速度会受到xterm滚动等工作的严重限制。如果你使用管道过滤掉不必要的行,你会看到速度的显著提高,例如

./program | grep -v "The variable"

如果刷新是个问题,您可以实现一个流缓冲区,该缓冲区覆盖sync()成员函数,以便在指定的情况下只刷新到外部设备。如果您打算在整个程序中更改这些首选项,它还必须创建自己的操纵器flush_on_endlnoflush_on_endl

#include <iostream>
static int disable() {
static int index(std::ios_base::xalloc());
return index;
}
class save_buffer
{
public:
save_buffer(std::ios& other)
: str(other), buf(other.rdbuf())
{ }
~save_buffer() { str.rdbuf(buf); }
private:
std::ios& str;
std::streambuf* buf;
};
class syncing_buffer_optional : public std::streambuf, private save_buffer
{
public:
syncing_buffer_optional(std::ostream& other)
: save_buffer(other),
buf(other.rdbuf()),
disable_sync(other.iword(disable()))
{ }
std::streambuf::int_type overflow(std::streambuf::int_type c)
{
buf->sputc(c);
return 0;
}
int sync()
{
return disable_sync? 0: buf->pubsync();
}
private:
std::streambuf* buf;
bool disable_sync;
};
std::ostream& flush_on_endl(std::ostream& os)
{
os.iword(disable()) = false;
return os;
}
std::ostream& noflush_on_endl(std::ostream& os)
{
os.iword(disable()) = true;
return os;
}

std::ostream& endl(std::ostream& os)
{
syncing_buffer_optional eb(os);
os.rdbuf(&eb);
return os << std::endl;
}
int main()
{
std::cout << noflush_on_endl << endl;
}